Skip to content

Commit c1acc20

Browse files
formatCvtdrelaptop
authored andcommitted
Add Android P cutout area support (#19286)
* Add Android P cutout area support Related #19285 * coding style fix * Update AppActivity.java Fix android build * suppress lint new api errors
1 parent e71ef82 commit c1acc20

File tree

4 files changed

+117
-0
lines changed

4 files changed

+117
-0
lines changed

Diff for: cocos/platform/android/CCGLViewImpl-android.cpp

+29
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@ Rect GLViewImpl::getSafeAreaRect() const {
144144

145145
bool isScreenRound = JniHelper::callStaticBooleanMethod("org/cocos2dx/lib/Cocos2dxHelper", "isScreenRound");
146146
bool hasSoftKeys = JniHelper::callStaticBooleanMethod("org/cocos2dx/lib/Cocos2dxHelper", "hasSoftKeys");
147+
bool isCutoutEnabled = JniHelper::callStaticBooleanMethod("org/cocos2dx/lib/Cocos2dxHelper", "isCutoutEnabled");
148+
147149
if(isScreenRound) {
148150
// edge screen (ex. Samsung Galaxy s7, s9, s9+, Note 9, Nokia 8 Sirocco, Sony Xperia XZ3, Oppo Find X...)
149151
if(safeAreaRect.size.width < safeAreaRect.size.height) {
@@ -184,6 +186,33 @@ Rect GLViewImpl::getSafeAreaRect() const {
184186
}
185187
}
186188

189+
if (isCutoutEnabled) {
190+
// screen with enabled cutout area (ex. Google Pixel 3 XL, Huawei P20, Asus ZenFone 5, etc)
191+
static int* safeInsets = JniHelper::callStaticIntArrayMethod("org/cocos2dx/lib/Cocos2dxHelper", "getSafeInsets");
192+
if (safeInsets != nullptr) {
193+
float safeInsetBottom = safeInsets[0] / _scaleY;
194+
float safeInsetLeft = safeInsets[1] / _scaleX;
195+
float safeInsetRight = safeInsets[2] / _scaleX;
196+
float safeInsetTop = safeInsets[3] / _scaleY;
197+
198+
// fit safe area rect with safe insets
199+
if (safeInsetBottom > 0) {
200+
safeAreaRect.origin.y += safeInsetBottom;
201+
safeAreaRect.size.height -= safeInsetBottom;
202+
}
203+
if (safeInsetLeft > 0) {
204+
safeAreaRect.origin.x += safeInsetLeft;
205+
safeAreaRect.size.width -= safeInsetLeft;
206+
}
207+
if (safeInsetRight > 0) {
208+
safeAreaRect.size.width -= safeInsetRight;
209+
}
210+
if (safeInsetTop > 0) {
211+
safeAreaRect.size.height -= safeInsetTop;
212+
}
213+
}
214+
}
215+
187216
return safeAreaRect;
188217
}
189218

Diff for: cocos/platform/android/java/src/org/cocos2dx/lib/Cocos2dxHelper.java

+47
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ of this software and associated documentation files (the "Software"), to deal
2525
****************************************************************************/
2626
package org.cocos2dx.lib;
2727

28+
import android.annotation.SuppressLint;
2829
import android.content.pm.PackageManager;
30+
import android.graphics.Rect;
2931
import android.media.AudioManager;
3032
import android.app.Activity;
3133
import android.content.ComponentName;
@@ -47,9 +49,11 @@ of this software and associated documentation files (the "Software"), to deal
4749
import android.util.DisplayMetrics;
4850
import android.util.Log;
4951
import android.view.Display;
52+
import android.view.DisplayCutout;
5053
import android.view.KeyCharacterMap;
5154
import android.view.KeyEvent;
5255
import android.view.ViewConfiguration;
56+
import android.view.Window;
5357
import android.view.WindowManager;
5458

5559
import com.android.vending.expansion.zipfile.APKExpansionSupport;
@@ -64,6 +68,7 @@ of this software and associated documentation files (the "Software"), to deal
6468
import java.lang.reflect.InvocationTargetException;
6569
import java.lang.reflect.Method;
6670
import java.util.LinkedHashSet;
71+
import java.util.List;
6772
import java.util.Locale;
6873
import java.util.Map;
6974
import java.util.Set;
@@ -771,6 +776,48 @@ public static boolean isScreenRound() {
771776
return false;
772777
}
773778

779+
/**
780+
* Returns whether the window is always allowed to extend into the DisplayCutout areas on the short edges of the screen.
781+
*
782+
* @return true if the window in display cutout mode on the short edges of the screen, false otherwise
783+
*/
784+
@SuppressLint("InlinedApi")
785+
public static boolean isCutoutEnabled() {
786+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
787+
WindowManager.LayoutParams lp = sActivity.getWindow().getAttributes();
788+
return lp.layoutInDisplayCutoutMode == WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
789+
}
790+
791+
return false;
792+
}
793+
794+
/**
795+
* Returns safe insets array.
796+
*
797+
* @return array of int with safe insets values
798+
*/
799+
@SuppressLint("NewApi")
800+
public static int[] getSafeInsets() {
801+
final int[] safeInsets = new int[]{0, 0, 0, 0};
802+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
803+
Window cocosWindow = sActivity.getWindow();
804+
DisplayCutout displayCutout = cocosWindow.getDecorView().getRootWindowInsets().getDisplayCutout();
805+
// Judge whether it is cutouts (aka notch) screen phone by judge cutout equle to null
806+
if (displayCutout != null) {
807+
List<Rect> rects = displayCutout.getBoundingRects();
808+
// Judge whether it is cutouts (aka notch) screen phone by judge cutout rects is null or zero size
809+
if (rects != null && rects.size() != 0) {
810+
safeInsets[0] = displayCutout.getSafeInsetBottom();
811+
safeInsets[1] = displayCutout.getSafeInsetLeft();
812+
safeInsets[2] = displayCutout.getSafeInsetRight();
813+
safeInsets[3] = displayCutout.getSafeInsetTop();
814+
}
815+
}
816+
}
817+
818+
return safeInsets;
819+
}
820+
774821
/**
775822
* Queries about whether any physical keys exist on the
776823
* any keyboard attached to the device and returns <code>true</code>

Diff for: cocos/platform/android/jni/JniHelper.h

+31
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,37 @@ class CC_DLL JniHelper
188188
return nullptr;
189189
}
190190

191+
/**
192+
@brief Call of Java static int* method
193+
@return address of JniMethodInfo if there are proper JniMethodInfo; otherwise nullptr.
194+
*/
195+
template <typename... Ts>
196+
static int* callStaticIntArrayMethod(const std::string& className,
197+
const std::string& methodName,
198+
Ts... xs) {
199+
static int ret[32];
200+
cocos2d::JniMethodInfo t;
201+
std::string signature = "(" + std::string(getJNISignature(xs...)) + ")[I";
202+
if (cocos2d::JniHelper::getStaticMethodInfo(t, className.c_str(), methodName.c_str(), signature.c_str())) {
203+
LocalRefMapType localRefs;
204+
jintArray array = (jintArray) t.env->CallStaticObjectMethod(t.classID, t.methodID, convert(localRefs, t, xs)...);
205+
jsize len = t.env->GetArrayLength(array);
206+
if (len <= 32) {
207+
jint* elems = t.env->GetIntArrayElements(array, 0);
208+
if (elems) {
209+
memcpy(ret, elems, sizeof(int) * len);
210+
t.env->ReleaseIntArrayElements(array, elems, 0);
211+
};
212+
}
213+
t.env->DeleteLocalRef(t.classID);
214+
deleteLocalRefs(t.env, localRefs);
215+
return &ret[0];
216+
} else {
217+
reportError(className, methodName, signature);
218+
}
219+
return nullptr;
220+
}
221+
191222
/**
192223
@brief Call of Java static Vec3 method
193224
@return JniMethodInfo of Vec3 type if there are proper JniMethodInfo; otherwise Vec3(0, 0, 0).

Diff for: templates/cpp-template-default/proj.android/app/src/org/cocos2dx/cpp/AppActivity.java

+10
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ of this software and associated documentation files (the "Software"), to deal
2626

2727
import android.os.Bundle;
2828
import org.cocos2dx.lib.Cocos2dxActivity;
29+
import android.os.Build;
30+
import android.view.WindowManager;
31+
import android.view.WindowManager.LayoutParams;
2932

3033
public class AppActivity extends Cocos2dxActivity {
3134

@@ -41,6 +44,13 @@ protected void onCreate(Bundle savedInstanceState) {
4144
// Don't need to finish it again since it's finished in super.onCreate .
4245
return;
4346
}
47+
// Make sure we're running on Pie or higher to change cutout mode
48+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
49+
// Enable rendering into the cutout area
50+
WindowManager.LayoutParams lp = getWindow().getAttributes();
51+
lp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
52+
getWindow().setAttributes(lp);
53+
}
4454
// DO OTHER INITIALIZATION BELOW
4555

4656
}

0 commit comments

Comments
 (0)