Android: fix fullscreen handling

Commit a35a7fcb5a713956e97bc87ccbd273737c7418df introduced the usage
of insets to correctly take into account the default Android status bars
and other reserved regions.

However in practice that does not work as expected - the bottom inset
is always reported to be non-zero, even when fullscreen mode is enabled.
To fix the issue, FLAG_FULLSCREEN is explicitly checked before applying
the insets.

Fixes: QTBUG-99624
Pick-to: 6.3 6.2
Change-Id: I8b25f0b06447cd452c42ef072493e3137e25f38b
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
This commit is contained in:
Ivan Solovev 2022-03-21 17:35:29 +01:00
parent 3033d89674
commit d85c6527b5
2 changed files with 57 additions and 5 deletions

View File

@ -49,6 +49,7 @@ import android.view.Display;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowInsets;
import android.view.WindowManager;
public class QtLayout extends ViewGroup
{
@ -112,11 +113,25 @@ public class QtLayout extends ViewGroup
}
boolean isFullScreenView = h == realMetrics.heightPixels;
int insetLeft = isFullScreenView ? insets.getSystemWindowInsetLeft() : 0;
int insetTop = isFullScreenView ? insets.getSystemWindowInsetTop() : 0;
int insetRight = isFullScreenView ? insets.getSystemWindowInsetRight() : 0;
int insetBottom = isFullScreenView ? insets.getSystemWindowInsetBottom() : 0;
// 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;

View File

@ -445,6 +445,10 @@ private slots:
void activateWhileModalHidden();
#ifdef Q_OS_ANDROID
void showFullscreenAndroid();
#endif
private:
const QString m_platform;
QSize m_testWidgetSize;
@ -12693,5 +12697,38 @@ void tst_QWidget::activateWhileModalHidden()
QCOMPARE(QApplication::activeWindow(), &window);
}
#ifdef Q_OS_ANDROID
void tst_QWidget::showFullscreenAndroid()
{
QWidget w;
w.setAutoFillBackground(true);
QPalette p = w.palette();
p.setColor(QPalette::Window, Qt::red);
w.setPalette(p);
// Need to toggle showFullScreen() twice, see QTBUG-101968
w.showFullScreen();
QVERIFY(QTest::qWaitForWindowExposed(&w));
w.show();
QVERIFY(QTest::qWaitForWindowExposed(&w));
w.showFullScreen();
QVERIFY(QTest::qWaitForWindowExposed(&w));
// Make sure that the lower part of the screen contains the red widget, not
// the buttons.
const QRect fullGeometry = w.screen()->geometry();
// Take a rect of (20 x 20) from the bottom area
const QRect grabArea(10, fullGeometry.height() - 30, 20, 20);
const QImage img = grabFromWidget(&w, grabArea).toImage().convertedTo(QImage::Format_RGB32);
QPixmap expectedPix(20, 20);
expectedPix.fill(Qt::red);
const QImage expectedImg = expectedPix.toImage().convertedTo(QImage::Format_RGB32);
QCOMPARE(img, expectedImg);
}
#endif // Q_OS_ANDROID
QTEST_MAIN(tst_QWidget)
#include "tst_qwidget.moc"