diff options
author | BogDan Vatra <bogdan@kde.org> | 2020-10-13 18:19:59 +0300 |
---|---|---|
committer | Ivan Solovev <ivan.solovev@qt.io> | 2022-01-28 00:22:41 +0100 |
commit | c1a93b20ff1fec370b2483276b74f07eb54486ef (patch) | |
tree | 7fa22aa519672ba7fb13e89108fd79f25bb475a2 /src | |
parent | e76d27d3ed2475169166a8666a3d90a82444fdbf (diff) |
[Android]: Handle the screen name, modes and refreshRate properly
Fixes: QTBUG-87136
Fixes: QTBUG-93823
Fixes: QTBUG-94959
Pick-to: 6.3 6.2 5.15
Change-Id: Id480e22611ec949b5e3ee780fc695fb502a5950c
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
Diffstat (limited to 'src')
9 files changed, 154 insertions, 97 deletions
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 3c387f1f9d..8cf71597e4 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java @@ -69,6 +69,7 @@ import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; +import android.view.Display; import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.Menu; @@ -698,8 +699,13 @@ public class QtActivityDelegate @Override public void onDisplayChanged(int displayId) { - m_currentRotation = m_activity.getWindowManager().getDefaultDisplay().getRotation(); + Display display = (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) + ? m_activity.getWindowManager().getDefaultDisplay() + : m_activity.getDisplay(); + m_currentRotation = display.getRotation(); QtNative.handleOrientationChanged(m_currentRotation, m_nativeOrientation); + float refreshRate = display.getRefreshRate(); + QtNative.handleRefreshRateChanged(refreshRate); } @Override @@ -830,6 +836,11 @@ public class QtActivityDelegate QtNative.handleOrientationChanged(rotation, m_nativeOrientation); m_currentRotation = rotation; + float refreshRate = (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) + ? m_activity.getWindowManager().getDefaultDisplay().getRefreshRate() + : m_activity.getDisplay().getRefreshRate(); + QtNative.handleRefreshRateChanged(refreshRate); + m_layout.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { 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 a65df48a17..2e52770cc5 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtLayout.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtLayout.java @@ -42,8 +42,10 @@ package org.qtproject.qt.android; import android.app.Activity; import android.content.Context; +import android.os.Build; import android.util.AttributeSet; import android.util.DisplayMetrics; +import android.view.Display; import android.view.View; import android.view.ViewGroup; import android.view.WindowInsets; @@ -73,7 +75,10 @@ public class QtLayout extends ViewGroup WindowInsets insets = getRootWindowInsets(); DisplayMetrics realMetrics = new DisplayMetrics(); - ((Activity) getContext()).getWindowManager().getDefaultDisplay().getRealMetrics(realMetrics); + Display display = (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) + ? ((Activity)getContext()).getWindowManager().getDefaultDisplay() + : ((Activity)getContext()).getDisplay(); + display.getRealMetrics(realMetrics); boolean isFullScreenView = h == realMetrics.heightPixels; @@ -85,16 +90,10 @@ public class QtLayout extends ViewGroup 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); + QtNative.setApplicationDisplayMetrics( + realMetrics.widthPixels, realMetrics.heightPixels, insetLeft, insetTop, + usableAreaWidth, usableAreaHeight, realMetrics.xdpi, realMetrics.ydpi, + realMetrics.scaledDensity, realMetrics.density, display.getRefreshRate()); if (m_startApplicationRunnable != null) { m_startApplicationRunnable.run(); diff --git a/src/android/jar/src/org/qtproject/qt/android/QtNative.java b/src/android/jar/src/org/qtproject/qt/android/QtNative.java index 3c26e6d4f2..11b27f96c0 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtNative.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtNative.java @@ -103,6 +103,7 @@ public class QtNative private static int m_displayMetricsAvailableTopPixels = 0; private static int m_displayMetricsAvailableWidthPixels = 0; private static int m_displayMetricsAvailableHeightPixels = 0; + private static float m_displayMetricsRefreshRate = 60; private static double m_displayMetricsXDpi = .0; private static double m_displayMetricsYDpi = .0; private static double m_displayMetricsScaledDensity = 1.0; @@ -634,16 +635,13 @@ public class QtNative @Override public void run() { res[0] = startQtAndroidPlugin(qtParams, environment); - setDisplayMetrics(m_displayMetricsScreenWidthPixels, - m_displayMetricsScreenHeightPixels, - m_displayMetricsAvailableLeftPixels, - m_displayMetricsAvailableTopPixels, - m_displayMetricsAvailableWidthPixels, - m_displayMetricsAvailableHeightPixels, - m_displayMetricsXDpi, - m_displayMetricsYDpi, - m_displayMetricsScaledDensity, - m_displayMetricsDensity); + setDisplayMetrics( + m_displayMetricsScreenWidthPixels, m_displayMetricsScreenHeightPixels, + m_displayMetricsAvailableLeftPixels, m_displayMetricsAvailableTopPixels, + m_displayMetricsAvailableWidthPixels, + m_displayMetricsAvailableHeightPixels, m_displayMetricsXDpi, + m_displayMetricsYDpi, m_displayMetricsScaledDensity, + m_displayMetricsDensity, m_displayMetricsRefreshRate); } }); m_qtThread.post(new Runnable() { @@ -658,16 +656,12 @@ public class QtNative return res[0]; } - public static void setApplicationDisplayMetrics(int screenWidthPixels, - int screenHeightPixels, - int availableLeftPixels, - int availableTopPixels, + public static void setApplicationDisplayMetrics(int screenWidthPixels, int screenHeightPixels, + int availableLeftPixels, int availableTopPixels, int availableWidthPixels, - int availableHeightPixels, - double XDpi, - double YDpi, - double scaledDensity, - double density) + int availableHeightPixels, double XDpi, + double YDpi, double scaledDensity, + double density, float refreshRate) { /* Fix buggy dpi report */ if (XDpi < android.util.DisplayMetrics.DENSITY_LOW) @@ -677,16 +671,9 @@ public class QtNative synchronized (m_mainActivityMutex) { if (m_started) { - setDisplayMetrics(screenWidthPixels, - screenHeightPixels, - availableLeftPixels, - availableTopPixels, - availableWidthPixels, - availableHeightPixels, - XDpi, - YDpi, - scaledDensity, - density); + setDisplayMetrics(screenWidthPixels, screenHeightPixels, availableLeftPixels, + availableTopPixels, availableWidthPixels, availableHeightPixels, + XDpi, YDpi, scaledDensity, density, refreshRate); } else { m_displayMetricsScreenWidthPixels = screenWidthPixels; m_displayMetricsScreenHeightPixels = screenHeightPixels; @@ -698,6 +685,7 @@ public class QtNative m_displayMetricsYDpi = YDpi; m_displayMetricsScaledDensity = scaledDensity; m_displayMetricsDensity = density; + m_displayMetricsRefreshRate = refreshRate; } } } @@ -1368,17 +1356,13 @@ public class QtNative } // 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); + 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); // screen methods // pointer methods diff --git a/src/android/jar/src/org/qtproject/qt/android/QtServiceDelegate.java b/src/android/jar/src/org/qtproject/qt/android/QtServiceDelegate.java index 2fbc4a70be..e0195b2bd2 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtServiceDelegate.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtServiceDelegate.java @@ -116,7 +116,7 @@ public class QtServiceDelegate QtNative.setService(m_service, this); QtNative.setClassLoader(classLoader); - QtNative.setApplicationDisplayMetrics(10, 10, 0, 0, 10, 10, 120, 120, 1.0, 1.0); + QtNative.setApplicationDisplayMetrics(10, 10, 0, 0, 10, 10, 120, 120, 1.0, 1.0, 60.0f); if (loaderParams.containsKey(STATIC_INIT_CLASSES_KEY)) { for (String className : diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp index c5cb056739..e99dca17a2 100644 --- a/src/plugins/platforms/android/androidjnimain.cpp +++ b/src/plugins/platforms/android/androidjnimain.cpp @@ -641,12 +641,11 @@ static void setSurface(JNIEnv *env, jobject /*thiz*/, jint id, jobject jSurface, surfaceClient->surfaceChanged(env, jSurface, w, h); } -static void setDisplayMetrics(JNIEnv */*env*/, jclass /*clazz*/, - jint screenWidthPixels, jint screenHeightPixels, - jint availableLeftPixels, jint availableTopPixels, - jint availableWidthPixels, jint availableHeightPixels, - jdouble xdpi, jdouble ydpi, - jdouble scaledDensity, jdouble density) +static void setDisplayMetrics(JNIEnv * /*env*/, jclass /*clazz*/, jint screenWidthPixels, + jint screenHeightPixels, jint availableLeftPixels, + jint availableTopPixels, jint availableWidthPixels, + jint availableHeightPixels, jdouble xdpi, jdouble ydpi, + jdouble scaledDensity, jdouble density, jfloat refreshRate) { m_availableWidthPixels = availableWidthPixels; m_availableHeightPixels = availableHeightPixels; @@ -655,20 +654,18 @@ static void setDisplayMetrics(JNIEnv */*env*/, jclass /*clazz*/, QMutexLocker lock(&m_platformMutex); if (!m_androidPlatformIntegration) { - QAndroidPlatformIntegration::setDefaultDisplayMetrics(availableLeftPixels, - availableTopPixels, - availableWidthPixels, - availableHeightPixels, - qRound(double(screenWidthPixels) / xdpi * 25.4), - qRound(double(screenHeightPixels) / ydpi * 25.4), - screenWidthPixels, - screenHeightPixels); + QAndroidPlatformIntegration::setDefaultDisplayMetrics( + availableLeftPixels, availableTopPixels, availableWidthPixels, + availableHeightPixels, qRound(double(screenWidthPixels) / xdpi * 25.4), + qRound(double(screenHeightPixels) / ydpi * 25.4), screenWidthPixels, + screenHeightPixels); } else { m_androidPlatformIntegration->setPhysicalSize(qRound(double(screenWidthPixels) / xdpi * 25.4), qRound(double(screenHeightPixels) / ydpi * 25.4)); m_androidPlatformIntegration->setScreenSize(screenWidthPixels, screenHeightPixels); m_androidPlatformIntegration->setAvailableGeometry(QRect(availableLeftPixels, availableTopPixels, availableWidthPixels, availableHeightPixels)); + m_androidPlatformIntegration->setRefreshRate(refreshRate); } } @@ -769,6 +766,12 @@ static void handleOrientationChanged(JNIEnv */*env*/, jobject /*thiz*/, jint new } } +static void handleRefreshRateChanged(JNIEnv */*env*/, jclass /*cls*/, jfloat refreshRate) +{ + if (m_androidPlatformIntegration) + m_androidPlatformIntegration->setRefreshRate(refreshRate); +} + static void onActivityResult(JNIEnv */*env*/, jclass /*cls*/, jint requestCode, jint resultCode, @@ -788,20 +791,22 @@ static jobject onBind(JNIEnv */*env*/, jclass /*cls*/, jobject intent) } static JNINativeMethod methods[] = { - {"startQtAndroidPlugin", "(Ljava/lang/String;Ljava/lang/String;)Z", (void *)startQtAndroidPlugin}, - {"startQtApplication", "()V", (void *)startQtApplication}, - {"quitQtAndroidPlugin", "()V", (void *)quitQtAndroidPlugin}, - {"quitQtCoreApplication", "()V", (void *)quitQtCoreApplication}, - {"terminateQt", "()V", (void *)terminateQt}, - {"waitForServiceSetup", "()V", (void *)waitForServiceSetup}, - {"setDisplayMetrics", "(IIIIIIDDDD)V", (void *)setDisplayMetrics}, - {"setSurface", "(ILjava/lang/Object;II)V", (void *)setSurface}, - {"updateWindow", "()V", (void *)updateWindow}, - {"updateApplicationState", "(I)V", (void *)updateApplicationState}, - {"handleOrientationChanged", "(II)V", (void *)handleOrientationChanged}, - {"onActivityResult", "(IILandroid/content/Intent;)V", (void *)onActivityResult}, - {"onNewIntent", "(Landroid/content/Intent;)V", (void *)onNewIntent}, - {"onBind", "(Landroid/content/Intent;)Landroid/os/IBinder;", (void *)onBind} + { "startQtAndroidPlugin", "(Ljava/lang/String;Ljava/lang/String;)Z", + (void *)startQtAndroidPlugin }, + { "startQtApplication", "()V", (void *)startQtApplication }, + { "quitQtAndroidPlugin", "()V", (void *)quitQtAndroidPlugin }, + { "quitQtCoreApplication", "()V", (void *)quitQtCoreApplication }, + { "terminateQt", "()V", (void *)terminateQt }, + { "waitForServiceSetup", "()V", (void *)waitForServiceSetup }, + { "setDisplayMetrics", "(IIIIIIDDDDF)V", (void *)setDisplayMetrics }, + { "setSurface", "(ILjava/lang/Object;II)V", (void *)setSurface }, + { "updateWindow", "()V", (void *)updateWindow }, + { "updateApplicationState", "(I)V", (void *)updateApplicationState }, + { "handleOrientationChanged", "(II)V", (void *)handleOrientationChanged }, + { "onActivityResult", "(IILandroid/content/Intent;)V", (void *)onActivityResult }, + { "onNewIntent", "(Landroid/content/Intent;)V", (void *)onNewIntent }, + { "onBind", "(Landroid/content/Intent;)Landroid/os/IBinder;", (void *)onBind }, + { "handleRefreshRateChanged", "(F)V", (void *)handleRefreshRateChanged } }; #define FIND_AND_CHECK_CLASS(CLASS_NAME) \ diff --git a/src/plugins/platforms/android/qandroidplatformintegration.cpp b/src/plugins/platforms/android/qandroidplatformintegration.cpp index c9ef977816..8f2b7970f1 100644 --- a/src/plugins/platforms/android/qandroidplatformintegration.cpp +++ b/src/plugins/platforms/android/qandroidplatformintegration.cpp @@ -472,14 +472,10 @@ QPlatformTheme *QAndroidPlatformIntegration::createPlatformTheme(const QString & return 0; } -void QAndroidPlatformIntegration::setDefaultDisplayMetrics(int availableLeft, - int availableTop, - int availableWidth, - int availableHeight, - int physicalWidth, - int physicalHeight, - int screenWidth, - int screenHeight) +void QAndroidPlatformIntegration::setDefaultDisplayMetrics(int availableLeft, int availableTop, + int availableWidth, int availableHeight, + int physicalWidth, int physicalHeight, + int screenWidth, int screenHeight) { m_defaultAvailableGeometry = QRect(availableLeft, availableTop, availableWidth, availableHeight); @@ -526,6 +522,12 @@ void QAndroidPlatformIntegration::setScreenSize(int width, int height) QMetaObject::invokeMethod(m_primaryScreen, "setSize", Qt::AutoConnection, Q_ARG(QSize, QSize(width, height))); } +void QAndroidPlatformIntegration::setRefreshRate(qreal refreshRate) +{ + if (m_primaryScreen) + QMetaObject::invokeMethod(m_primaryScreen, "setRefreshRate", Qt::AutoConnection, + Q_ARG(qreal, refreshRate)); +} #if QT_CONFIG(vulkan) QPlatformVulkanInstance *QAndroidPlatformIntegration::createPlatformVulkanInstance(QVulkanInstance *instance) const diff --git a/src/plugins/platforms/android/qandroidplatformintegration.h b/src/plugins/platforms/android/qandroidplatformintegration.h index 52442e87af..4fffed651b 100644 --- a/src/plugins/platforms/android/qandroidplatformintegration.h +++ b/src/plugins/platforms/android/qandroidplatformintegration.h @@ -99,6 +99,7 @@ public: void setAvailableGeometry(const QRect &availableGeometry); void setPhysicalSize(int width, int height); void setScreenSize(int width, int height); + void setRefreshRate(qreal refreshRate); bool isVirtualDesktop() { return true; } QPlatformFontDatabase *fontDatabase() const override; @@ -121,14 +122,9 @@ public: QStringList themeNames() const override; QPlatformTheme *createPlatformTheme(const QString &name) const override; - static void setDefaultDisplayMetrics(int availableLeft, - int availableTop, - int availableWidth, - int availableHeight, - int physicalWidth, - int physicalHeight, - int screenWidth, - int screenHeight); + static void setDefaultDisplayMetrics(int availableLeft, int availableTop, int availableWidth, + int availableHeight, int physicalWidth, int physicalHeight, + int screenWidth, int screenHeight); static void setScreenOrientation(Qt::ScreenOrientation currentOrientation, Qt::ScreenOrientation nativeOrientation); diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp index 1463351c77..59c8f396af 100644 --- a/src/plugins/platforms/android/qandroidplatformscreen.cpp +++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp @@ -55,10 +55,11 @@ #include <android/native_window_jni.h> #include <qguiapplication.h> +#include <QtCore/QJniObject> +#include <QtCore/QJniEnvironment> #include <QtGui/QGuiApplication> #include <QtGui/QWindow> #include <QtGui/private/qwindow_p.h> - #include <vector> QT_BEGIN_NAMESPACE @@ -103,6 +104,46 @@ QAndroidPlatformScreen::QAndroidPlatformScreen() } m_physicalSize = QAndroidPlatformIntegration::m_defaultPhysicalSize; connect(qGuiApp, &QGuiApplication::applicationStateChanged, this, &QAndroidPlatformScreen::applicationStateChanged); + + QJniObject activity(QtAndroid::activity()); + if (!activity.isValid()) + return; + QJniObject display; + if (QNativeInterface::QAndroidApplication::sdkVersion() < 30) { + display = activity.callObjectMethod("getWindowManager", "()Landroid/view/WindowManager;") + .callObjectMethod("getDefaultDisplay", "()Landroid/view/Display;"); + } else { + display = activity.callObjectMethod("getDisplay", "()Landroid/view/Display;"); + } + if (!display.isValid()) + return; + + m_name = display.callObjectMethod("getName", "()Ljava/lang/String;").toString(); + m_refreshRate = display.callMethod<jfloat>("getRefreshRate"); + + if (QNativeInterface::QAndroidApplication::sdkVersion() < 23) { + m_modes << Mode { .size = m_physicalSize.toSize(), .refreshRate = m_refreshRate }; + return; + } + + QJniEnvironment env; + const jint currentMode = display.callObjectMethod("getMode", "()Landroid/view/Display$Mode;") + .callMethod<jint>("getModeId"); + const auto modes = display.callObjectMethod("getSupportedModes", + "()[Landroid/view/Display$Mode;"); + const auto modesArray = jobjectArray(modes.object()); + const auto sz = env->GetArrayLength(modesArray); + for (jsize i = 0; i < sz; ++i) { + auto mode = QJniObject::fromLocalRef(env->GetObjectArrayElement(modesArray, i)); + if (currentMode == mode.callMethod<jint>("getModeId")) + m_currentMode = m_modes.size(); + m_modes << Mode { .size = QSize { mode.callMethod<jint>("getPhysicalHeight"), + mode.callMethod<jint>("getPhysicalWidth") }, + .refreshRate = mode.callMethod<jfloat>("getRefreshRate") }; + } + + if (m_modes.isEmpty()) + m_modes << Mode { .size = m_physicalSize.toSize(), .refreshRate = m_refreshRate }; } QAndroidPlatformScreen::~QAndroidPlatformScreen() @@ -242,6 +283,14 @@ void QAndroidPlatformScreen::setSize(const QSize &size) QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry(), availableGeometry()); } +void QAndroidPlatformScreen::setRefreshRate(qreal refreshRate) +{ + if (refreshRate == m_refreshRate) + return; + m_refreshRate = refreshRate; + QWindowSystemInterface::handleScreenRefreshRateChange(QPlatformScreen::screen(), refreshRate); +} + void QAndroidPlatformScreen::setAvailableGeometry(const QRect &rect) { QMutexLocker lock(&m_surfaceMutex); diff --git a/src/plugins/platforms/android/qandroidplatformscreen.h b/src/plugins/platforms/android/qandroidplatformscreen.h index edddc9c557..e0de85277a 100644 --- a/src/plugins/platforms/android/qandroidplatformscreen.h +++ b/src/plugins/platforms/android/qandroidplatformscreen.h @@ -69,6 +69,12 @@ public: QImage::Format format() const override { return m_format; } QSizeF physicalSize() const override { return m_physicalSize; } + QString name() const override { return m_name; } + QList<Mode> modes() const override { return m_modes; } + int currentMode() const override { return m_currentMode; } + int preferredMode() const override { return m_currentMode; } + qreal refreshRate() const override { return m_refreshRate; } + inline QWindow *topWindow() const; QWindow *topLevelAt(const QPoint & p) const override; @@ -87,6 +93,7 @@ public slots: void setPhysicalSize(const QSize &size); void setAvailableGeometry(const QRect &rect); void setSize(const QSize &size); + void setRefreshRate(qreal refreshRate); protected: bool event(QEvent *event) override; @@ -100,6 +107,10 @@ protected: int m_depth; QImage::Format m_format; QSizeF m_physicalSize; + qreal m_refreshRate; + QString m_name; + QList<Mode> m_modes; + int m_currentMode = 0; private: QDpi logicalDpi() const override; |