Skip to content

Commit 1d9154a

Browse files
formatCvtMike Chen
authored and
Mike Chen
committed
Add Android P cutout area support (cocos2d#19286)
* Add Android P cutout area support Related cocos2d#19285 * coding style fix * Update AppActivity.java Fix android build * suppress lint new api errors (cherry picked from commit c1acc20)
1 parent 0c39d77 commit 1d9154a

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
@@ -153,6 +153,8 @@ Rect GLViewImpl::getSafeAreaRect() const {
153153

154154
bool isScreenRound = JniHelper::callStaticBooleanMethod("org/cocos2dx/lib/Cocos2dxHelper", "isScreenRound");
155155
bool hasSoftKeys = JniHelper::callStaticBooleanMethod("org/cocos2dx/lib/Cocos2dxHelper", "hasSoftKeys");
156+
bool isCutoutEnabled = JniHelper::callStaticBooleanMethod("org/cocos2dx/lib/Cocos2dxHelper", "isCutoutEnabled");
157+
156158
if(isScreenRound) {
157159
// edge screen (ex. Samsung Galaxy s7, s9, s9+, Note 9, Nokia 8 Sirocco, Sony Xperia XZ3, Oppo Find X...)
158160
if(safeAreaRect.size.width < safeAreaRect.size.height) {
@@ -193,6 +195,33 @@ Rect GLViewImpl::getSafeAreaRect() const {
193195
}
194196
}
195197

198+
if (isCutoutEnabled) {
199+
// screen with enabled cutout area (ex. Google Pixel 3 XL, Huawei P20, Asus ZenFone 5, etc)
200+
static int* safeInsets = JniHelper::callStaticIntArrayMethod("org/cocos2dx/lib/Cocos2dxHelper", "getSafeInsets");
201+
if (safeInsets != nullptr) {
202+
float safeInsetBottom = safeInsets[0] / _scaleY;
203+
float safeInsetLeft = safeInsets[1] / _scaleX;
204+
float safeInsetRight = safeInsets[2] / _scaleX;
205+
float safeInsetTop = safeInsets[3] / _scaleY;
206+
207+
// fit safe area rect with safe insets
208+
if (safeInsetBottom > 0) {
209+
safeAreaRect.origin.y += safeInsetBottom;
210+
safeAreaRect.size.height -= safeInsetBottom;
211+
}
212+
if (safeInsetLeft > 0) {
213+
safeAreaRect.origin.x += safeInsetLeft;
214+
safeAreaRect.size.width -= safeInsetLeft;
215+
}
216+
if (safeInsetRight > 0) {
217+
safeAreaRect.size.width -= safeInsetRight;
218+
}
219+
if (safeInsetTop > 0) {
220+
safeAreaRect.size.height -= safeInsetTop;
221+
}
222+
}
223+
}
224+
196225
return safeAreaRect;
197226
}
198227

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

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

27+
import android.annotation.SuppressLint;
2728
import android.content.pm.PackageManager;
29+
import android.graphics.Rect;
2830
import android.media.AudioManager;
2931
import android.app.Activity;
3032
import android.content.ComponentName;
@@ -46,9 +48,11 @@ of this software and associated documentation files (the "Software"), to deal
4648
import android.util.DisplayMetrics;
4749
import android.util.Log;
4850
import android.view.Display;
51+
import android.view.DisplayCutout;
4952
import android.view.KeyCharacterMap;
5053
import android.view.KeyEvent;
5154
import android.view.ViewConfiguration;
55+
import android.view.Window;
5256
import android.view.WindowManager;
5357
import android.hardware.SensorManager;
5458

@@ -63,6 +67,7 @@ of this software and associated documentation files (the "Software"), to deal
6367
import java.lang.reflect.InvocationTargetException;
6468
import java.lang.reflect.Method;
6569
import java.util.LinkedHashSet;
70+
import java.util.List;
6671
import java.util.Locale;
6772
import java.util.Map;
6873
import java.util.Set;
@@ -863,6 +868,48 @@ public static boolean isScreenRound() {
863868
return false;
864869
}
865870

871+
/**
872+
* Returns whether the window is always allowed to extend into the DisplayCutout areas on the short edges of the screen.
873+
*
874+
* @return true if the window in display cutout mode on the short edges of the screen, false otherwise
875+
*/
876+
@SuppressLint("InlinedApi")
877+
public static boolean isCutoutEnabled() {
878+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
879+
WindowManager.LayoutParams lp = sActivity.getWindow().getAttributes();
880+
return lp.layoutInDisplayCutoutMode == WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
881+
}
882+
883+
return false;
884+
}
885+
886+
/**
887+
* Returns safe insets array.
888+
*
889+
* @return array of int with safe insets values
890+
*/
891+
@SuppressLint("NewApi")
892+
public static int[] getSafeInsets() {
893+
final int[] safeInsets = new int[]{0, 0, 0, 0};
894+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
895+
Window cocosWindow = sActivity.getWindow();
896+
DisplayCutout displayCutout = cocosWindow.getDecorView().getRootWindowInsets().getDisplayCutout();
897+
// Judge whether it is cutouts (aka notch) screen phone by judge cutout equle to null
898+
if (displayCutout != null) {
899+
List<Rect> rects = displayCutout.getBoundingRects();
900+
// Judge whether it is cutouts (aka notch) screen phone by judge cutout rects is null or zero size
901+
if (rects != null && rects.size() != 0) {
902+
safeInsets[0] = displayCutout.getSafeInsetBottom();
903+
safeInsets[1] = displayCutout.getSafeInsetLeft();
904+
safeInsets[2] = displayCutout.getSafeInsetRight();
905+
safeInsets[3] = displayCutout.getSafeInsetTop();
906+
}
907+
}
908+
}
909+
910+
return safeInsets;
911+
}
912+
866913
/**
867914
* Queries about whether any physical keys exist on the
868915
* 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
@@ -186,6 +186,37 @@ class CC_DLL JniHelper
186186
return nullptr;
187187
}
188188

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

Diff for: tests/game-controller-test/proj.android/src/org/cocos2dx/game_controller_test/AppActivity.java

+10
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,22 @@ of this software and associated documentation files (the "Software"), to deal
2727
//import org.cocos2dx.lib.GameControllerHelper.ControllerListener;
2828

2929
import android.os.Bundle;
30+
import android.os.Build;
31+
import android.view.WindowManager;
32+
import android.view.WindowManager.LayoutParams;
3033

3134
public class AppActivity extends GameControllerActivity {
3235

3336
@Override
3437
protected void onCreate(Bundle savedInstanceState) {
3538
super.onCreate(savedInstanceState);
39+
}
40+
// Make sure we're running on Pie or higher to change cutout mode
41+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
42+
// Enable rendering into the cutout area
43+
WindowManager.LayoutParams lp = getWindow().getAttributes();
44+
lp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
45+
getWindow().setAttributes(lp);
3646

3747
//The standard controller,without doing anything special. e.g: Amazon Fire TV
3848

0 commit comments

Comments
 (0)