diff options
Diffstat (limited to 'src/android/jar/src/org/qtproject/qt/android/QtLayout.java')
-rw-r--r-- | src/android/jar/src/org/qtproject/qt/android/QtLayout.java | 142 |
1 files changed, 107 insertions, 35 deletions
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtLayout.java b/src/android/jar/src/org/qtproject/qt/android/QtLayout.java index 6c52a00422..5ff46fc96b 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtLayout.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtLayout.java @@ -42,7 +42,9 @@ package org.qtproject.qt.android; import android.app.Activity; import android.content.Context; +import android.graphics.Rect; import android.os.Build; +import android.util.Log; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.view.Display; @@ -50,6 +52,10 @@ import android.view.View; import android.view.ViewGroup; import android.view.WindowInsets; import android.view.WindowManager; +import android.graphics.Insets; +import android.view.WindowMetrics; +import android.content.res.Configuration; +import android.content.res.Resources; public class QtLayout extends ViewGroup { @@ -93,15 +99,95 @@ public class QtLayout extends ViewGroup @Override protected void onSizeChanged (int w, int h, int oldw, int oldh) { - WindowInsets insets = getRootWindowInsets(); + Activity activity = (Activity)getContext(); + if (activity == null) + return; + + final WindowManager windowManager = activity.getWindowManager(); + Display display; + + int appWidth = 0; + int appHeight = 0; + + int insetLeft = 0; + int insetTop = 0; + + int maxWidth = 0; + int maxHeight = 0; + + double xdpi = 0; + double ydpi = 0; + double scaledDensity = 0; + double density = 0; + + if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.R) { + display = windowManager.getDefaultDisplay(); + + final DisplayMetrics appMetrics = new DisplayMetrics(); + display.getMetrics(appMetrics); + + final WindowInsets rootInsets = getRootWindowInsets(); + + insetLeft = rootInsets.getStableInsetLeft(); + insetTop = rootInsets.getStableInsetTop(); - DisplayMetrics realMetrics = new DisplayMetrics(); - Display display = (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) - ? ((Activity)getContext()).getWindowManager().getDefaultDisplay() - : ((Activity)getContext()).getDisplay(); - display.getRealMetrics(realMetrics); + appWidth = appMetrics.widthPixels - rootInsets.getStableInsetRight() + rootInsets.getStableInsetLeft(); - if ((realMetrics.widthPixels > realMetrics.heightPixels) != (w > h)) { + if (android.os.Build.VERSION.SDK_INT == Build.VERSION_CODES.Q) { + appHeight = appMetrics.heightPixels - rootInsets.getStableInsetTop(); + } else { + appHeight = appMetrics.heightPixels - rootInsets.getStableInsetTop() + rootInsets.getStableInsetBottom(); + } + + final DisplayMetrics maxMetrics = new DisplayMetrics(); + display.getRealMetrics(maxMetrics); + + maxWidth = maxMetrics.widthPixels; + maxHeight = maxMetrics.heightPixels; + + density = appMetrics.density; + xdpi = appMetrics.xdpi; + ydpi = appMetrics.ydpi; + scaledDensity = appMetrics.scaledDensity; + + } else { + // after API 30 use getCurrentWindowMetrics for application metrics + // getMaximumWindowMetrics for the screen metrics + // resource configuration for density as best practice + // and the resource display metrics for the rest + display = activity.getDisplay(); + + final WindowMetrics appMetrics = windowManager.getCurrentWindowMetrics(); + final WindowMetrics maxMetrics = windowManager.getMaximumWindowMetrics(); + + final WindowInsets windowInsets = appMetrics.getWindowInsets(); + Insets statusBarInsets = windowInsets.getInsetsIgnoringVisibility(WindowInsets.Type.statusBars()); + Insets cutoutInsets = windowInsets.getInsetsIgnoringVisibility(WindowInsets.Type.displayCutout()); + Insets imeInsets = windowInsets.getInsets(WindowInsets.Type.ime()); + + insetLeft = cutoutInsets.left; + insetTop = statusBarInsets.top; + + appWidth = w; + appHeight = h - imeInsets.bottom; + + maxWidth = maxMetrics.getBounds().width(); + maxHeight = maxMetrics.getBounds().height(); + + final Resources resources = activity.getResources(); + final Configuration configuration = resources.getConfiguration(); + density = configuration.densityDpi / (float) DisplayMetrics.DENSITY_DEFAULT; + + final DisplayMetrics displayMetrics = resources.getDisplayMetrics(); + xdpi = displayMetrics.xdpi; + ydpi = displayMetrics.ydpi; + density = displayMetrics.density; + scaledDensity = displayMetrics.scaledDensity; + } + + float refreshRate = display.getRefreshRate(); + + if ((appWidth > appHeight) != (w > h)) { // This is an intermediate state during display rotation. // The new size is still reported for old orientation, while // realMetrics contain sizes for new orientation. Setting @@ -112,34 +198,20 @@ public class QtLayout extends ViewGroup return; } - boolean isFullScreenView = h == realMetrics.heightPixels; - // The code uses insets for fullscreen mode only. However in practice - // the insets can be reported incorrectly. Both on Android 6 and Android 11 - // a non-zero bottom inset is reported even when the - // WindowManager.LayoutParams.FLAG_FULLSCREEN flag is set. - // To avoid that, add an extra check for the fullscreen mode. - // The insets-related logic is not removed for the case when - // isFullScreenView == true, but hasFlagFullscreen == false, although - // I can't get such case in my tests. - final int windowFlags = ((Activity)getContext()).getWindow().getAttributes().flags; - final boolean hasFlagFullscreen = - (windowFlags & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0; - int insetLeft = - (isFullScreenView && !hasFlagFullscreen) ? insets.getSystemWindowInsetLeft() : 0; - int insetTop = - (isFullScreenView && !hasFlagFullscreen) ? insets.getSystemWindowInsetTop() : 0; - int insetRight = - (isFullScreenView && !hasFlagFullscreen) ? insets.getSystemWindowInsetRight() : 0; - int insetBottom = - (isFullScreenView && !hasFlagFullscreen) ? insets.getSystemWindowInsetBottom() : 0; - - int usableAreaWidth = w - insetLeft - insetRight; - int usableAreaHeight = h - insetTop - insetBottom; - - QtNative.setApplicationDisplayMetrics( - realMetrics.widthPixels, realMetrics.heightPixels, insetLeft, insetTop, - usableAreaWidth, usableAreaHeight, realMetrics.xdpi, realMetrics.ydpi, - realMetrics.scaledDensity, realMetrics.density, display.getRefreshRate()); + final int flag = + activity.getWindow().getAttributes().flags & WindowManager.LayoutParams.FLAG_FULLSCREEN; + + if (flag == WindowManager.LayoutParams.FLAG_FULLSCREEN || h == maxHeight) { + // immersive mode uses the whole screen + appWidth = maxWidth; + appHeight = maxHeight; + insetLeft = insetTop = 0; + } + + QtNative.setApplicationDisplayMetrics(maxWidth, maxHeight, insetLeft, + insetTop, appWidth, appHeight, + xdpi,ydpi,scaledDensity, density, + refreshRate); int newRotation = display.getRotation(); if (m_ownDisplayRotation != m_activityDisplayRotation |