diff options
Diffstat (limited to 'src/android/jar/src/org/qtproject')
6 files changed, 170 insertions, 47 deletions
diff --git a/src/android/jar/src/org/qtproject/qt/android/CursorHandle.java b/src/android/jar/src/org/qtproject/qt/android/CursorHandle.java index d754b3b620..c15a654b79 100644 --- a/src/android/jar/src/org/qtproject/qt/android/CursorHandle.java +++ b/src/android/jar/src/org/qtproject/qt/android/CursorHandle.java @@ -124,8 +124,7 @@ public class CursorHandle implements ViewTreeObserver.OnPreDrawListener m_id = id; m_attr = attr; m_layout = layout; - DisplayMetrics metrics = new DisplayMetrics(); - activity.getWindowManager().getDefaultDisplay().getMetrics(metrics); + DisplayMetrics metrics = activity.getResources().getDisplayMetrics(); m_yShift = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_MM, 1f, metrics); tolerance = Math.min(1, (int)(m_yShift / 2f)); m_lastX = m_lastY = -1 - tolerance; diff --git a/src/android/jar/src/org/qtproject/qt/android/ExtractStyle.java b/src/android/jar/src/org/qtproject/qt/android/ExtractStyle.java index 8c391a7e7b..109a0e5d93 100644 --- a/src/android/jar/src/org/qtproject/qt/android/ExtractStyle.java +++ b/src/android/jar/src/org/qtproject/qt/android/ExtractStyle.java @@ -70,6 +70,7 @@ import android.graphics.drawable.ScaleDrawable; import android.graphics.drawable.StateListDrawable; import android.graphics.drawable.VectorDrawable; import android.os.Build; +import android.os.Bundle; import android.util.AttributeSet; import android.util.Log; import android.util.TypedValue; @@ -171,6 +172,42 @@ public class ExtractStyle { Context m_context; private final HashMap<String, DrawableCache> m_drawableCache = new HashMap<>(); + private static final String EXTRACT_STYLE_KEY = "extract.android.style"; + private static final String EXTRACT_STYLE_MINIMAL_KEY = "extract.android.style.option"; + + private static boolean m_missingNormalStyle = false; + private static boolean m_missingDarkStyle = false; + private static String m_stylePath = null; + private static boolean m_extractMinimal = false; + + public static void setup(Bundle loaderParams) { + if (loaderParams.containsKey(EXTRACT_STYLE_KEY)) { + m_stylePath = loaderParams.getString(EXTRACT_STYLE_KEY); + + boolean darkModeFileMissing = !(new File(m_stylePath + "darkUiMode/style.json").exists()); + m_missingDarkStyle = Build.VERSION.SDK_INT > 28 && darkModeFileMissing; + + m_missingNormalStyle = !(new File(m_stylePath + "style.json").exists()); + + m_extractMinimal = loaderParams.containsKey(EXTRACT_STYLE_MINIMAL_KEY) && + loaderParams.getBoolean(EXTRACT_STYLE_MINIMAL_KEY); + } + } + + public static void runIfNeeded(Context context, boolean extractDarkMode) { + if (m_stylePath == null) + return; + if (extractDarkMode) { + if (m_missingDarkStyle) { + new ExtractStyle(context, m_stylePath + "darkUiMode/", m_extractMinimal); + m_missingDarkStyle = false; + } + } else if (m_missingNormalStyle) { + new ExtractStyle(context, m_stylePath, m_extractMinimal); + m_missingNormalStyle = false; + } + } + public ExtractStyle(Context context, String extractPath, boolean minimal) { m_minimal = minimal; m_extractPath = extractPath + "/"; diff --git a/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java index 7d49fb71b1..1c6c0dad2d 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java @@ -120,8 +120,6 @@ public class QtActivityDelegate private static final String ENVIRONMENT_VARIABLES_KEY = "environment.variables"; private static final String APPLICATION_PARAMETERS_KEY = "application.parameters"; private static final String STATIC_INIT_CLASSES_KEY = "static.init.classes"; - private static final String EXTRACT_STYLE_KEY = "extract.android.style"; - private static final String EXTRACT_STYLE_MINIMAL_KEY = "extract.android.style.option"; public static final int SYSTEM_UI_VISIBILITY_NORMAL = 0; public static final int SYSTEM_UI_VISIBILITY_FULLSCREEN = 1; @@ -743,11 +741,8 @@ public class QtActivityDelegate libraries.remove(libraries.size() - 1); } - if (loaderParams.containsKey(EXTRACT_STYLE_KEY)) { - String path = loaderParams.getString(EXTRACT_STYLE_KEY); - new ExtractStyle(m_activity, path, loaderParams.containsKey(EXTRACT_STYLE_MINIMAL_KEY) && - loaderParams.getBoolean(EXTRACT_STYLE_MINIMAL_KEY)); - } + ExtractStyle.setup(loaderParams); + ExtractStyle.runIfNeeded(m_activity, isUiModeDark(m_activity.getResources().getConfiguration())); try { m_super_dispatchKeyEvent = m_activity.getClass().getMethod("super_dispatchKeyEvent", KeyEvent.class); @@ -1025,13 +1020,20 @@ public class QtActivityDelegate updateFullScreen(); } + boolean isUiModeDark(Configuration config) + { + return (config.uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES; + } + private void handleUiModeChange(int uiMode) { switch (uiMode) { case Configuration.UI_MODE_NIGHT_NO: + ExtractStyle.runIfNeeded(m_activity, false); QtNative.handleUiDarkModeChanged(0); break; case Configuration.UI_MODE_NIGHT_YES: + ExtractStyle.runIfNeeded(m_activity, true); QtNative.handleUiDarkModeChanged(1); break; } diff --git a/src/android/jar/src/org/qtproject/qt/android/QtInputConnection.java b/src/android/jar/src/org/qtproject/qt/android/QtInputConnection.java index 6cf1aca5bf..a6930e4d97 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtInputConnection.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtInputConnection.java @@ -41,6 +41,8 @@ package org.qtproject.qt.android; import android.content.Context; +import android.os.Build; +import android.view.WindowMetrics; import android.view.inputmethod.BaseInputConnection; import android.view.inputmethod.CompletionInfo; import android.view.inputmethod.ExtractedText; @@ -94,9 +96,17 @@ class HideKeyboardRunnable implements Runnable { Activity activity = QtNative.activity(); Rect r = new Rect(); activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(r); - DisplayMetrics metrics = new DisplayMetrics(); - activity.getWindowManager().getDefaultDisplay().getMetrics(metrics); - final int kbHeight = metrics.heightPixels - r.bottom; + + int screenHeight = 0; + if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.R) { + DisplayMetrics metrics = new DisplayMetrics(); + activity.getWindowManager().getDefaultDisplay().getMetrics(metrics); + screenHeight = metrics.heightPixels; + } else { + final WindowMetrics maximumWindowMetrics = activity.getWindowManager().getMaximumWindowMetrics(); + screenHeight = maximumWindowMetrics.getBounds().height(); + } + final int kbHeight = screenHeight - r.bottom; if (kbHeight < 100) QtNative.activityDelegate().setKeyboardVisibility(false, m_hideTimeStamp); } 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 diff --git a/src/android/jar/src/org/qtproject/qt/android/accessibility/QtAccessibilityDelegate.java b/src/android/jar/src/org/qtproject/qt/android/accessibility/QtAccessibilityDelegate.java index 4ed6d66b42..88312cbdbd 100644 --- a/src/android/jar/src/org/qtproject/qt/android/accessibility/QtAccessibilityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt/android/accessibility/QtAccessibilityDelegate.java @@ -57,6 +57,7 @@ import android.view.MotionEvent; import android.view.View.OnHoverListener; import android.content.Context; +import android.system.Os; import java.util.LinkedList; import java.util.List; @@ -124,6 +125,8 @@ public class QtAccessibilityDelegate extends View.AccessibilityDelegate @Override public void onAccessibilityStateChanged(boolean enabled) { + if (Os.getenv("QT_ANDROID_DISABLE_ACCESSIBILITY") != null) + return; if (enabled) { try { View view = m_view; |