[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>
This commit is contained in:
BogDan Vatra 2020-10-13 18:19:59 +03:00 committed by Ivan Solovev
parent e76d27d3ed
commit c1a93b20ff
9 changed files with 154 additions and 97 deletions

View File

@ -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() {

View File

@ -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();

View File

@ -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,
setDisplayMetrics(
m_displayMetricsScreenWidthPixels, m_displayMetricsScreenHeightPixels,
m_displayMetricsAvailableLeftPixels, m_displayMetricsAvailableTopPixels,
m_displayMetricsAvailableWidthPixels,
m_displayMetricsAvailableHeightPixels,
m_displayMetricsXDpi,
m_displayMetricsYDpi,
m_displayMetricsScaledDensity,
m_displayMetricsDensity);
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

View File

@ -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 :

View File

@ -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,13 +654,10 @@ 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,
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),
@ -669,6 +665,7 @@ static void setDisplayMetrics(JNIEnv */*env*/, jclass /*clazz*/,
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},
{ "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},
{ "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}
{ "onBind", "(Landroid/content/Intent;)Landroid/os/IBinder;", (void *)onBind },
{ "handleRefreshRateChanged", "(F)V", (void *)handleRefreshRateChanged }
};
#define FIND_AND_CHECK_CLASS(CLASS_NAME) \

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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;