summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java8
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtDisplayManager.java105
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtLayout.java54
-rw-r--r--tests/auto/corelib/platform/android/BLACKLIST2
-rw-r--r--tests/auto/corelib/platform/android/CMakeLists.txt1
-rw-r--r--tests/auto/corelib/platform/android/tst_android.cpp26
6 files changed, 103 insertions, 93 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 5ebce6dc35..6a87c187be 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java
@@ -135,7 +135,7 @@ class QtActivityDelegate
{
m_layout = new QtLayout(m_activity);
- m_displayManager = new QtDisplayManager(m_activity, m_layout);
+ m_displayManager = new QtDisplayManager(m_activity);
m_displayManager.registerDisplayListener();
QtInputDelegate.KeyboardVisibilityListener keyboardVisibilityListener =
@@ -179,11 +179,7 @@ class QtActivityDelegate
m_activity.setContentView(m_layout,
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
-
- int rotation = m_activity.getWindowManager().getDefaultDisplay().getRotation();
- int nativeOrientation = QtDisplayManager.getNativeOrientation(m_activity, rotation);
- m_layout.setNativeOrientation(nativeOrientation);
- QtDisplayManager.handleOrientationChanged(rotation, nativeOrientation);
+ QtDisplayManager.handleOrientationChanges(m_activity, false);
handleUiModeChange(m_activity.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK);
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtDisplayManager.java b/src/android/jar/src/org/qtproject/qt/android/QtDisplayManager.java
index b5347596f8..80c89526ec 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtDisplayManager.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtDisplayManager.java
@@ -44,45 +44,30 @@ class QtDisplayManager {
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, QtLayout layout)
+ QtDisplayManager(Activity activity)
{
m_activity = activity;
- initDisplayListener(layout);
+ initDisplayListener();
}
- private void initDisplayListener(QtLayout layout) {
+ private void initDisplayListener() {
m_displayListener = new DisplayManager.DisplayListener() {
@Override
public void onDisplayAdded(int displayId) {
QtDisplayManager.handleScreenAdded(displayId);
}
- private boolean isSimilarRotation(int r1, int r2) {
- return (r1 == r2)
- || (r1 == Surface.ROTATION_0 && r2 == Surface.ROTATION_180)
- || (r1 == Surface.ROTATION_180 && r2 == Surface.ROTATION_0)
- || (r1 == Surface.ROTATION_90 && r2 == Surface.ROTATION_270)
- || (r1 == Surface.ROTATION_270 && r2 == Surface.ROTATION_90);
- }
-
@Override
public void onDisplayChanged(int displayId) {
+ handleOrientationChanges(m_activity, false);
Display display = (Build.VERSION.SDK_INT < Build.VERSION_CODES.R)
? m_activity.getWindowManager().getDefaultDisplay()
: m_activity.getDisplay();
- int rotation = display != null ? display.getRotation() : Surface.ROTATION_0;
- layout.setActivityDisplayRotation(rotation);
- // Process orientation change only if it comes after the size
- // change, or if the screen is rotated by 180 degrees.
- // Otherwise it will be processed in QtLayout.
- if (isSimilarRotation(rotation, layout.displayRotation())) {
- QtDisplayManager.handleOrientationChanged(rotation,
- getNativeOrientation(m_activity, rotation));
- }
-
float refreshRate = getRefreshRate(display);
QtDisplayManager.handleRefreshRateChanged(refreshRate);
QtDisplayManager.handleScreenChanged(displayId);
@@ -95,6 +80,53 @@ class QtDisplayManager {
};
}
+ private static boolean isSameSizeForOrientations(int r1, int r2) {
+ return (r1 == r2) ||
+ (r1 == Surface.ROTATION_0 && r2 == Surface.ROTATION_180)
+ || (r1 == Surface.ROTATION_180 && r2 == Surface.ROTATION_0)
+ || (r1 == Surface.ROTATION_90 && r2 == Surface.ROTATION_270)
+ || (r1 == Surface.ROTATION_270 && r2 == Surface.ROTATION_90);
+ }
+
+ static void handleOrientationChanges(Activity activity, boolean sizeChanged)
+ {
+ int currentRotation = getDisplayRotation(activity);
+ int nativeOrientation = getNativeOrientation(activity, currentRotation);
+
+ if (m_previousRotation == currentRotation)
+ return;
+
+ // If the the current and previous rotations are similar then QtLayout.onSizeChanged()
+ // might not be called, so we can already update the orientation, and rely on this to
+ // called again once the resize event is sent.
+ // Note: Android 10 emulator seems to not always send an event when the orientation
+ // changes, could be a bug in the emulator.
+ boolean noResizeNeeded = isSameSizeForOrientations(m_previousRotation, currentRotation);
+ if (m_previousRotation == -1 || sizeChanged || noResizeNeeded) {
+ QtDisplayManager.handleOrientationChanged(currentRotation, nativeOrientation);
+ m_previousRotation = currentRotation;
+ }
+ }
+
+ private 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;
@@ -114,21 +146,6 @@ class QtDisplayManager {
displayManager.unregisterDisplayListener(m_displayListener);
}
- public static int getNativeOrientation(Activity activity, int rotation)
- {
- int nativeOrientation;
-
- 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))
- nativeOrientation = Configuration.ORIENTATION_LANDSCAPE;
- else
- nativeOrientation = Configuration.ORIENTATION_PORTRAIT;
-
- return nativeOrientation;
- }
-
public void setSystemUiVisibility(int systemUiVisibility)
{
if (m_systemUiVisibility == systemUiVisibility)
@@ -283,20 +300,4 @@ class QtDisplayManager {
width, height, xdpi, ydpi,
scaledDensity, density, getRefreshRate(display));
}
-
- public static int getDisplayRotation(Activity activity) {
- Display display;
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
- final WindowManager windowManager = activity.getWindowManager();
- display = windowManager.getDefaultDisplay();
- } else {
- display = activity.getDisplay();
- }
-
- int newRotation = 0;
- if (display != null) {
- newRotation = display.getRotation();
- }
- return newRotation;
- }
}
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 8732a5f612..2643a9afcf 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtLayout.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtLayout.java
@@ -1,4 +1,4 @@
-// Copyright (C) 2022 The Qt Company Ltd.
+// Copyright (C) 2023 The Qt Company Ltd.
// Copyright (C) 2012 BogDan Vatra <bogdan@kde.org>
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
@@ -6,31 +6,15 @@ 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;
class QtLayout extends ViewGroup
{
- private int m_activityDisplayRotation = -1;
- private int m_ownDisplayRotation = -1;
- private int m_nativeOrientation = -1;
-
- public void setActivityDisplayRotation(int rotation)
- {
- m_activityDisplayRotation = rotation;
- }
-
- public void setNativeOrientation(int orientation)
- {
- m_nativeOrientation = orientation;
- }
-
- public int displayRotation()
- {
- return m_ownDisplayRotation;
- }
-
public QtLayout(Context context)
{
super(context);
@@ -53,18 +37,28 @@ class QtLayout extends ViewGroup
if (activity == null)
return;
- QtDisplayManager.setApplicationDisplayMetrics(activity, w, h);
+ DisplayMetrics realMetrics = new DisplayMetrics();
+ Display display = (Build.VERSION.SDK_INT < Build.VERSION_CODES.R)
+ ? activity.getWindowManager().getDefaultDisplay()
+ : activity.getDisplay();
+
+ if (display == null)
+ return;
- int newRotation = QtDisplayManager.getDisplayRotation(activity);
- if (m_ownDisplayRotation != m_activityDisplayRotation
- && newRotation == m_activityDisplayRotation) {
- // If the saved rotation value does not match the one from the
- // activity, it means that we got orientation change before size
- // change, and the value was cached. So we need to notify about
- // orientation change now.
- QtDisplayManager.handleOrientationChanged(newRotation, m_nativeOrientation);
+ display.getRealMetrics(realMetrics);
+ if ((realMetrics.widthPixels > realMetrics.heightPixels) != (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
+ // such parameters will produce inconsistent results, so
+ // we just skip them.
+ // We will have another onSizeChanged() with normal values
+ // a bit later.
+ return;
}
- m_ownDisplayRotation = newRotation;
+
+ QtDisplayManager.setApplicationDisplayMetrics(activity, w, h);
+ QtDisplayManager.handleOrientationChanges(activity, true);
}
@Override
diff --git a/tests/auto/corelib/platform/android/BLACKLIST b/tests/auto/corelib/platform/android/BLACKLIST
deleted file mode 100644
index 8b5c0990f1..0000000000
--- a/tests/auto/corelib/platform/android/BLACKLIST
+++ /dev/null
@@ -1,2 +0,0 @@
-[orientationChange]
-android
diff --git a/tests/auto/corelib/platform/android/CMakeLists.txt b/tests/auto/corelib/platform/android/CMakeLists.txt
index 0f9f670cb0..6b7e9b2901 100644
--- a/tests/auto/corelib/platform/android/CMakeLists.txt
+++ b/tests/auto/corelib/platform/android/CMakeLists.txt
@@ -18,6 +18,7 @@ qt_internal_add_test(tst_android
Qt::CorePrivate
Qt::Gui
Qt::GuiPrivate
+ Qt::Widgets
)
if(ANDROID)
diff --git a/tests/auto/corelib/platform/android/tst_android.cpp b/tests/auto/corelib/platform/android/tst_android.cpp
index 9a503fafc5..02204abcb5 100644
--- a/tests/auto/corelib/platform/android/tst_android.cpp
+++ b/tests/auto/corelib/platform/android/tst_android.cpp
@@ -12,6 +12,8 @@
#include <qpa/qplatformscreen.h>
#include <qpa/qplatformnativeinterface.h>
#include <QtCore/qdiriterator.h>
+#include <QWidget>
+#include <QSignalSpy>
using namespace Qt::StringLiterals;
@@ -305,19 +307,37 @@ void tst_Android::orientationChange_data()
{
QTest::addColumn<int>("nativeOrientation");
QTest::addColumn<Qt::ScreenOrientation>("expected");
+ QTest::addColumn<QSize>("screenSize");
- QTest::newRow("Landscape") << 0 << Qt::LandscapeOrientation;
- QTest::newRow("Portrait") << 1 << Qt::PortraitOrientation;
+ const QSize portraitSize = QGuiApplication::primaryScreen()->size();
+ const QSize landscapeSize = QSize(portraitSize.height(), portraitSize.width());
+
+ QTest::newRow("InvertedLandscape") << 8 << Qt::InvertedLandscapeOrientation << landscapeSize;
+ QTest::newRow("InvertedPortrait") << 9 << Qt::InvertedPortraitOrientation << portraitSize;
+ QTest::newRow("Landscape") << 0 << Qt::LandscapeOrientation << landscapeSize;
+ // Leave Portrait till the end
+ QTest::newRow("Portrait") << 1 << Qt::PortraitOrientation << portraitSize;
}
void tst_Android::orientationChange()
{
QFETCH(int, nativeOrientation);
QFETCH(Qt::ScreenOrientation, expected);
+ QFETCH(QSize, screenSize);
+
+ // For QTBUG-94459 to check that the widget size are consistent after orientation changes
+ QWidget widget;
+ widget.show();
auto context = QNativeInterface::QAndroidApplication::context();
context.callMethod<void>("setRequestedOrientation", nativeOrientation);
- QTRY_COMPARE(qGuiApp->primaryScreen()->orientation(), expected);
+
+ QScreen *screen = QGuiApplication::primaryScreen();
+ QSignalSpy orientationSpy(screen, SIGNAL(orientationChanged(Qt::ScreenOrientation)));
+ QTRY_COMPARE(screen->orientation(), expected);
+ QCOMPARE(orientationSpy.size(), 1);
+ QCOMPARE(screen->size(), screenSize);
+ QCOMPARE(widget.size(), screen->availableSize());
}
QTEST_MAIN(tst_Android)