summaryrefslogtreecommitdiffstats
path: root/src/android/jar/src/org/qtproject/qt/android/QtDisplayManager.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/android/jar/src/org/qtproject/qt/android/QtDisplayManager.java')
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtDisplayManager.java287
1 files changed, 287 insertions, 0 deletions
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtDisplayManager.java b/src/android/jar/src/org/qtproject/qt/android/QtDisplayManager.java
new file mode 100644
index 0000000000..b6a52fb22f
--- /dev/null
+++ b/src/android/jar/src/org/qtproject/qt/android/QtDisplayManager.java
@@ -0,0 +1,287 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+package org.qtproject.qt.android;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.hardware.display.DisplayManager;
+import android.os.Build;
+import android.util.DisplayMetrics;
+import android.util.Size;
+import android.view.Display;
+import android.view.Surface;
+import android.view.View;
+import android.view.WindowInsets;
+import android.view.WindowManager;
+import android.view.WindowMetrics;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+class QtDisplayManager {
+
+ // screen methods
+ public static native void setDisplayMetrics(int screenWidthPixels, int screenHeightPixels,
+ int availableLeftPixels, int availableTopPixels,
+ int availableWidthPixels, int availableHeightPixels,
+ double XDpi, double YDpi, double scaledDensity,
+ double density, float refreshRate);
+ public static native void handleOrientationChanged(int newRotation, int nativeOrientation);
+ public static native void handleRefreshRateChanged(float refreshRate);
+ public static native void handleUiDarkModeChanged(int newUiMode);
+ public static native void handleScreenAdded(int displayId);
+ public static native void handleScreenChanged(int displayId);
+ public static native void handleScreenRemoved(int displayId);
+ // screen methods
+
+ // Keep in sync with QtAndroid::SystemUiVisibility in androidjnimain.h
+ public static final int SYSTEM_UI_VISIBILITY_NORMAL = 0;
+ public static final int SYSTEM_UI_VISIBILITY_FULLSCREEN = 1;
+ public static final int SYSTEM_UI_VISIBILITY_TRANSLUCENT = 2;
+ private int m_systemUiVisibility = SYSTEM_UI_VISIBILITY_NORMAL;
+
+ private static int m_previousRotation = -1;
+
+ private DisplayManager.DisplayListener m_displayListener = null;
+ private final Activity m_activity;
+
+ QtDisplayManager(Activity activity)
+ {
+ m_activity = activity;
+ initDisplayListener();
+ }
+
+ private void initDisplayListener() {
+ m_displayListener = new DisplayManager.DisplayListener() {
+ @Override
+ public void onDisplayAdded(int displayId) {
+ QtDisplayManager.handleScreenAdded(displayId);
+ }
+
+ @Override
+ public void onDisplayChanged(int displayId) {
+ Display display = (Build.VERSION.SDK_INT < Build.VERSION_CODES.R)
+ ? m_activity.getWindowManager().getDefaultDisplay()
+ : m_activity.getDisplay();
+ float refreshRate = getRefreshRate(display);
+ QtDisplayManager.handleRefreshRateChanged(refreshRate);
+ QtDisplayManager.handleScreenChanged(displayId);
+ }
+
+ @Override
+ public void onDisplayRemoved(int displayId) {
+ QtDisplayManager.handleScreenRemoved(displayId);
+ }
+ };
+ }
+
+ static void handleOrientationChanges(Activity activity)
+ {
+ int currentRotation = getDisplayRotation(activity);
+ if (m_previousRotation == currentRotation)
+ return;
+ int nativeOrientation = getNativeOrientation(activity, currentRotation);
+ QtDisplayManager.handleOrientationChanged(currentRotation, nativeOrientation);
+ m_previousRotation = currentRotation;
+ }
+
+ public static int getDisplayRotation(Activity activity) {
+ Display display = Build.VERSION.SDK_INT < Build.VERSION_CODES.R ?
+ activity.getWindowManager().getDefaultDisplay() :
+ activity.getDisplay();
+
+ return display != null ? display.getRotation() : 0;
+ }
+
+ private static int getNativeOrientation(Activity activity, int rotation)
+ {
+ int orientation = activity.getResources().getConfiguration().orientation;
+ boolean rot90 = (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270);
+ boolean isLandscape = (orientation == Configuration.ORIENTATION_LANDSCAPE);
+ if ((isLandscape && !rot90) || (!isLandscape && rot90))
+ return Configuration.ORIENTATION_LANDSCAPE;
+
+ return Configuration.ORIENTATION_PORTRAIT;
+ }
+
+ static float getRefreshRate(Display display)
+ {
+ return display != null ? display.getRefreshRate() : 60.0f;
+ }
+
+ public void registerDisplayListener()
+ {
+ DisplayManager displayManager =
+ (DisplayManager) m_activity.getSystemService(Context.DISPLAY_SERVICE);
+ displayManager.registerDisplayListener(m_displayListener, null);
+ }
+
+ public void unregisterDisplayListener()
+ {
+ DisplayManager displayManager =
+ (DisplayManager) m_activity.getSystemService(Context.DISPLAY_SERVICE);
+ displayManager.unregisterDisplayListener(m_displayListener);
+ }
+
+ public void setSystemUiVisibility(int systemUiVisibility)
+ {
+ if (m_systemUiVisibility == systemUiVisibility)
+ return;
+
+ m_systemUiVisibility = systemUiVisibility;
+
+ int systemUiVisibilityFlags = View.SYSTEM_UI_FLAG_VISIBLE;
+ switch (m_systemUiVisibility) {
+ case SYSTEM_UI_VISIBILITY_NORMAL:
+ m_activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
+ m_activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
+ m_activity.getWindow().getAttributes().layoutInDisplayCutoutMode =
+ WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER;
+ }
+ break;
+ case SYSTEM_UI_VISIBILITY_FULLSCREEN:
+ m_activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
+ m_activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
+ systemUiVisibilityFlags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
+ | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+ | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ | View.SYSTEM_UI_FLAG_FULLSCREEN
+ | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
+ | View.INVISIBLE;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
+ m_activity.getWindow().getAttributes().layoutInDisplayCutoutMode =
+ WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT;
+ }
+ break;
+ case SYSTEM_UI_VISIBILITY_TRANSLUCENT:
+ m_activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN
+ | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION
+ | WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+ m_activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ m_activity.getWindow().getAttributes().layoutInDisplayCutoutMode =
+ WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+ }
+ break;
+ }
+ m_activity.getWindow().getDecorView().setSystemUiVisibility(systemUiVisibilityFlags);
+ }
+
+ public int systemUiVisibility()
+ {
+ return m_systemUiVisibility;
+ }
+
+ public void updateFullScreen()
+ {
+ if (m_systemUiVisibility == SYSTEM_UI_VISIBILITY_FULLSCREEN) {
+ m_systemUiVisibility = SYSTEM_UI_VISIBILITY_NORMAL;
+ setSystemUiVisibility(SYSTEM_UI_VISIBILITY_FULLSCREEN);
+ }
+ }
+
+ @UsedFromNativeCode
+ public static Display getDisplay(Context context, int displayId)
+ {
+ DisplayManager displayManager =
+ (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
+ if (displayManager != null) {
+ return displayManager.getDisplay(displayId);
+ }
+ return null;
+ }
+
+ @UsedFromNativeCode
+ public static List<Display> getAvailableDisplays(Context context)
+ {
+ DisplayManager displayManager =
+ (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
+ if (displayManager != null) {
+ Display[] displays = displayManager.getDisplays();
+ return Arrays.asList(displays);
+ }
+ return new ArrayList<>();
+ }
+
+ @UsedFromNativeCode
+ public static Size getDisplaySize(Context displayContext, Display display)
+ {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
+ DisplayMetrics realMetrics = new DisplayMetrics();
+ display.getRealMetrics(realMetrics);
+ return new Size(realMetrics.widthPixels, realMetrics.heightPixels);
+ }
+
+ Context windowsContext = displayContext.createWindowContext(
+ WindowManager.LayoutParams.TYPE_APPLICATION, null);
+ WindowManager windowManager =
+ (WindowManager) windowsContext.getSystemService(Context.WINDOW_SERVICE);
+ WindowMetrics windowsMetrics = windowManager.getCurrentWindowMetrics();
+ Rect bounds = windowsMetrics.getBounds();
+ return new Size(bounds.width(), bounds.height());
+ }
+
+ public static void setApplicationDisplayMetrics(Activity activity, int width, int height)
+ {
+ if (activity == null)
+ return;
+
+ final WindowInsets rootInsets = activity.getWindow().getDecorView().getRootWindowInsets();
+ final WindowManager windowManager = activity.getWindowManager();
+ Display display;
+
+ int insetLeft;
+ int insetTop;
+
+ int maxWidth;
+ int maxHeight;
+
+ if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
+ display = windowManager.getDefaultDisplay();
+
+ final DisplayMetrics maxMetrics = new DisplayMetrics();
+ display.getRealMetrics(maxMetrics);
+ maxWidth = maxMetrics.widthPixels;
+ maxHeight = maxMetrics.heightPixels;
+
+ insetLeft = rootInsets.getStableInsetLeft();
+ insetTop = rootInsets.getStableInsetTop();
+ } else {
+ display = activity.getDisplay();
+
+ final WindowMetrics maxMetrics = windowManager.getMaximumWindowMetrics();
+ maxWidth = maxMetrics.getBounds().width();
+ maxHeight = maxMetrics.getBounds().height();
+
+ insetLeft = rootInsets.getInsetsIgnoringVisibility(WindowInsets.Type.systemBars()).left;
+ insetTop = rootInsets.getInsetsIgnoringVisibility(WindowInsets.Type.systemBars()).top;
+ }
+
+ final DisplayMetrics displayMetrics = activity.getResources().getDisplayMetrics();
+
+ double density = displayMetrics.density;
+ double scaledDensity = displayMetrics.scaledDensity;
+
+ setDisplayMetrics(maxWidth, maxHeight, insetLeft, insetTop,
+ width, height, getXDpi(displayMetrics), getYDpi(displayMetrics),
+ scaledDensity, density, getRefreshRate(display));
+ }
+
+ public static float getXDpi(final DisplayMetrics metrics) {
+ if (metrics.xdpi < android.util.DisplayMetrics.DENSITY_LOW)
+ return android.util.DisplayMetrics.DENSITY_LOW;
+ return metrics.xdpi;
+ }
+
+ public static float getYDpi(final DisplayMetrics metrics) {
+ if (metrics.ydpi < android.util.DisplayMetrics.DENSITY_LOW)
+ return android.util.DisplayMetrics.DENSITY_LOW;
+ return metrics.ydpi;
+ }
+}