Implement display cutout support for android

This commit is contained in:
Benau 2021-03-22 07:04:21 +08:00
parent c7e337f96f
commit 4ec4fda91b
6 changed files with 197 additions and 18 deletions

View File

@ -29,6 +29,7 @@ import android.os.Process;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.Display;
import android.view.DisplayCutout;
import android.view.Gravity;
import android.view.inputmethod.InputMethodManager;
import android.view.KeyEvent;
@ -39,6 +40,7 @@ import android.view.ViewGroup.MarginLayoutParams;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.View;
import android.view.Window;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.widget.FrameLayout;
@ -63,6 +65,12 @@ public class SuperTuxKartActivity extends SDLActivity
private ImageView m_splash_screen;
private STKEditText m_stk_edittext;
private int m_bottom_y;
private float m_top_padding;
private float m_bottom_padding;
private float m_left_padding;
private float m_right_padding;
// ------------------------------------------------------------------------
private native static void handlePadding(boolean val);
// ------------------------------------------------------------------------
private native static void saveKeyboardHeight(int height);
// ------------------------------------------------------------------------
@ -179,6 +187,8 @@ public class SuperTuxKartActivity extends SDLActivity
m_progress_bar = null;
m_splash_screen = null;
m_bottom_y = 0;
m_top_padding = m_bottom_padding = m_left_padding = m_right_padding =
0.0f;
final View root = getWindow().getDecorView().findViewById(
android.R.id.content);
root.getViewTreeObserver().addOnGlobalLayoutListener(new
@ -250,6 +260,11 @@ public class SuperTuxKartActivity extends SDLActivity
}
catch(Exception e) {}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
{
getWindow().getAttributes().layoutInDisplayCutoutMode =
LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
}
}
// ------------------------------------------------------------------------
@Override
@ -375,6 +390,14 @@ public class SuperTuxKartActivity extends SDLActivity
Configuration.SCREENLAYOUT_SIZE_MASK;
}
// ------------------------------------------------------------------------
public float getTopPadding() { return m_top_padding; }
// ------------------------------------------------------------------------
public float getBottomPadding() { return m_bottom_padding; }
// ------------------------------------------------------------------------
public float getLeftPadding() { return m_left_padding; }
// ------------------------------------------------------------------------
public float getRightPadding() { return m_right_padding; }
// ------------------------------------------------------------------------
public void showExtractProgress(final int progress)
{
runOnUiThread(new Runnable()
@ -447,4 +470,30 @@ public class SuperTuxKartActivity extends SDLActivity
});
}
}
// ------------------------------------------------------------------------
@Override
public void onAttachedToWindow()
{
super.onAttachedToWindow();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
{
DisplayCutout dc = getWindow().getDecorView().getRootWindowInsets()
.getDisplayCutout();
if (dc != null)
{
m_top_padding = (float)dc.getBoundingRectTop().height();
m_bottom_padding = (float)dc.getBoundingRectBottom().height();
m_left_padding = (float)dc.getBoundingRectLeft().width();
m_right_padding = (float)dc.getBoundingRectRight().width();
}
}
}
// ------------------------------------------------------------------------
@Override
public void onMultiWindowModeChanged(boolean isInMultiWindowMode,
Configuration newConfig)
{
handlePadding(isInMultiWindowMode);
}
}

View File

@ -18,6 +18,7 @@ using namespace irr;
// moving screen
std::atomic<int> g_keyboard_height(0);
std::atomic<int> g_moved_height(0);
std::atomic<int> g_disable_padding(0);
extern "C" int Android_getKeyboardHeight()
{
return g_keyboard_height.load();
@ -28,6 +29,11 @@ extern "C" int Android_getMovedHeight()
return g_moved_height.load();
}
extern "C" int Android_disablePadding()
{
return g_disable_padding.load();
}
#define MAKE_ANDROID_SAVE_KBD_HEIGHT_CALLBACK(x) JNIEXPORT void JNICALL Java_ ## x##_SuperTuxKartActivity_saveKeyboardHeight(JNIEnv* env, jclass cls, jint height)
#define ANDROID_SAVE_KBD_HEIGHT_CALLBACK(PKG_NAME) MAKE_ANDROID_SAVE_KBD_HEIGHT_CALLBACK(PKG_NAME)
@ -46,6 +52,65 @@ ANDROID_SAVE_MOVED_HEIGHT_CALLBACK(ANDROID_PACKAGE_CALLBACK_NAME)
g_moved_height.store((int)height);
}
#define MAKE_ANDROID_HANDLE_PADDING_CALLBACK(x) JNIEXPORT void JNICALL Java_ ## x##_SuperTuxKartActivity_handlePadding(JNIEnv* env, jclass cls, jboolean val)
#define ANDROID_HANDLE_PADDING_CALLBACK(PKG_NAME) MAKE_ANDROID_HANDLE_PADDING_CALLBACK(PKG_NAME)
extern "C"
ANDROID_HANDLE_PADDING_CALLBACK(ANDROID_PACKAGE_CALLBACK_NAME)
{
g_disable_padding.store((int)val);
}
extern "C" void Android_initDisplayCutout(float* top, float* bottom,
float* left, float* right)
{
JNIEnv* env = NULL;
jobject activity = NULL;
jclass class_native_activity = NULL;
jmethodID top_method = NULL;
jmethodID bottom_method = NULL;
jmethodID left_method = NULL;
jmethodID right_method = NULL;
env = (JNIEnv*)SDL_AndroidGetJNIEnv();
if (!env)
goto exit;
activity = (jobject)SDL_AndroidGetActivity();
if (!activity)
goto exit;
class_native_activity = env->GetObjectClass(activity);
if (class_native_activity == NULL)
goto exit;
top_method = env->GetMethodID(class_native_activity, "getTopPadding", "()F");
if (top_method == NULL)
goto exit;
*top = env->CallFloatMethod(activity, top_method);
bottom_method = env->GetMethodID(class_native_activity, "getBottomPadding", "()F");
if (bottom_method == NULL)
goto exit;
*bottom = env->CallFloatMethod(activity, bottom_method);
left_method = env->GetMethodID(class_native_activity, "getLeftPadding", "()F");
if (left_method == NULL)
goto exit;
*left = env->CallFloatMethod(activity, left_method);
right_method = env->GetMethodID(class_native_activity, "getRightPadding", "()F");
if (right_method == NULL)
goto exit;
*right = env->CallFloatMethod(activity, right_method);
exit:
if (!env)
return;
env->DeleteLocalRef(class_native_activity);
env->DeleteLocalRef(activity);
}
bool Android_isHardwareKeyboardConnected()
{
JNIEnv* env = (JNIEnv*)SDL_AndroidGetJNIEnv();

View File

@ -40,6 +40,8 @@ namespace irr
extern "C" void init_objc(SDL_SysWMinfo* info, float* top, float* bottom, float* left, float* right);
extern "C" int handle_app_event(void* userdata, SDL_Event* event);
extern "C" void Android_initDisplayCutout(float* top, float* bottom, float* left, float* right);
extern "C" int Android_disablePadding();
namespace irr
{
@ -110,6 +112,9 @@ CIrrDeviceSDL::CIrrDeviceSDL(const SIrrlichtCreationParameters& param)
#endif
#ifdef IOS_STK
init_objc(&Info, &TopPadding, &BottomPadding, &LeftPadding, &RightPadding);
#endif
#ifdef ANDROID
Android_initDisplayCutout(&TopPadding, &BottomPadding, &LeftPadding, &RightPadding);
#endif
core::stringc sdlversion = "SDL Version ";
sdlversion += Info.version.major;
@ -1404,6 +1409,59 @@ f32 CIrrDeviceSDL::getNativeScaleY() const
return g_native_scale_y;
}
s32 CIrrDeviceSDL::getTopPadding()
{
#ifdef ANDROID
if (Android_disablePadding() != 0)
return 0;
#endif
return TopPadding * getNativeScaleY();
}
s32 CIrrDeviceSDL::getBottomPadding()
{
#ifdef ANDROID
if (Android_disablePadding() != 0)
return 0;
#endif
return BottomPadding * getNativeScaleY();
}
s32 CIrrDeviceSDL::getLeftPadding()
{
#ifdef ANDROID
if (Android_disablePadding() != 0)
return 0;
#if SDL_VERSION_ATLEAST(2, 0, 9)
if (SDL_GetDisplayOrientation(0) == SDL_ORIENTATION_LANDSCAPE_FLIPPED)
return RightPadding;
#endif
return LeftPadding;
#else
return LeftPadding * getNativeScaleX();
#endif
}
s32 CIrrDeviceSDL::getRightPadding()
{
#ifdef ANDROID
#if SDL_VERSION_ATLEAST(2, 0, 9)
if (Android_disablePadding() != 0)
return 0;
if (SDL_GetDisplayOrientation(0) == SDL_ORIENTATION_LANDSCAPE_FLIPPED)
return LeftPadding;
#endif
return RightPadding;
#else
return RightPadding * getNativeScaleX();
#endif
}
} // end namespace irr
#endif // _IRR_COMPILE_WITH_SDL_DEVICE_

View File

@ -116,25 +116,13 @@ namespace irr
const SDL_SysWMinfo& getWMInfo() const { return Info; }
virtual s32 getTopPadding()
{
return TopPadding * getNativeScaleY();
}
virtual s32 getTopPadding();
virtual s32 getBottomPadding()
{
return BottomPadding * getNativeScaleY();
}
virtual s32 getBottomPadding();
virtual s32 getLeftPadding()
{
return LeftPadding * getNativeScaleX();
}
virtual s32 getLeftPadding();
virtual s32 getRightPadding()
{
return RightPadding * getNativeScaleX();
}
virtual s32 getRightPadding();
virtual f32 getNativeScaleX() const;
virtual f32 getNativeScaleY() const;

View File

@ -88,6 +88,13 @@
#include <irrlicht.h>
#if !defined(SERVER_ONLY) && defined(ANDROID)
#include <SDL.h>
#if SDL_VERSION_ATLEAST(2, 0, 9)
#define ENABLE_SCREEN_ORIENTATION_HANDLING 1
#endif
#endif
#ifdef ENABLE_RECORDER
#include <chrono>
#include <openglrecorder.h>
@ -157,6 +164,7 @@ const bool ALLOW_1280_X_720 = true;
*/
IrrDriver::IrrDriver()
{
m_screen_orientation = -1;
m_render_nw_debug = false;
m_resolution_changing = RES_CHANGE_NONE;
@ -773,7 +781,9 @@ void IrrDriver::initDevice()
m_device->getCursorControl()->setVisible(true);
#endif
m_pointer_shown = true;
#ifdef ENABLE_SCREEN_ORIENTATION_HANDLING
m_screen_orientation = (int)SDL_GetDisplayOrientation(0);
#endif
if (GUIEngine::isNoGraphics())
return;
} // initDevice
@ -1986,13 +1996,21 @@ void IrrDriver::handleWindowResize()
current_screen_size.Height = screen->getHeight();
}
bool screen_orientation_changed = false;
int new_orientation = -1;
#ifdef ENABLE_SCREEN_ORIENTATION_HANDLING
new_orientation = (int)SDL_GetDisplayOrientation(0);
screen_orientation_changed = m_screen_orientation != new_orientation;
#endif
if (m_actual_screen_size != m_video_driver->getCurrentRenderTargetSize() ||
current_screen_size != m_video_driver->getCurrentRenderTargetSize())
current_screen_size != m_video_driver->getCurrentRenderTargetSize() ||
screen_orientation_changed)
{
// Don't update when dialog is opened
if (dialog_exists)
return;
m_screen_orientation = new_orientation;
m_actual_screen_size = m_video_driver->getCurrentRenderTargetSize();
UserConfigParams::m_width = m_actual_screen_size.Width;
UserConfigParams::m_height = m_actual_screen_size.Height;

View File

@ -141,6 +141,7 @@ public:
private:
int m_screen_orientation;
std::vector<VideoMode> m_modes;
void setupViewports();