summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAssam Boudjelthia <assam.boudjelthia@qt.io>2025-08-30 04:59:52 +0300
committerAssam Boudjelthia <assam.boudjelthia@qt.io>2025-09-06 01:27:38 +0300
commite2a9ab46d39d442b198fe77d13153b8fc6b64a35 (patch)
tree381642a97e1c2ccb742034e252b31b0ae4073813 /src
parent357580c2253b2e1e5c09170a249cc59b2da30677 (diff)
Android: report margins only when window is under unsafe area
To avoid reporting margins/insets when it's not needed, like for some older Android versions, or to avoid wrong or improperly handled resize events, we only report the margins values for a window to reach the safe, otherwise, we could end up with extra padding from Qt safe margins and the system padding. Also, to ensure the root view location is up-to-date and avoid going into a race condition, we post() the safe margins reporting to the root view that way we ensure it's done after the root view has gone through the resize event. On safeAreaMarginsChanged() JNI implementation, don't do JNI calls to get the margin values unless the relevant platform window is found. Fixes: QTBUG-135808 Pick-to: 6.9 6.10 Change-Id: Idda072b8ebbd019c54ae6ae45f672bc7abb195b7 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtWindow.java62
-rw-r--r--src/plugins/platforms/android/qandroidplatformwindow.cpp35
2 files changed, 65 insertions, 32 deletions
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtWindow.java b/src/android/jar/src/org/qtproject/qt/android/QtWindow.java
index 8b96a7cdc35..7249e3ff017 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtWindow.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtWindow.java
@@ -87,9 +87,15 @@ class QtWindow extends QtLayout implements QtSurfaceInterface {
setOnApplyWindowInsetsListener((view, insets) -> {
WindowInsets windowInsets = view.onApplyWindowInsets(insets);
- Insets safeInsets = getSafeInsets(this, windowInsets);
- safeAreaMarginsChanged(safeInsets, getId());
- m_firstSafeMarginsDelivered = true;
+ ViewTreeObserver.OnPreDrawListener listener = new ViewTreeObserver.OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ reportSafeAreaMargins(windowInsets, getId());
+ m_firstSafeMarginsDelivered = true;
+ return true;
+ }
+ };
+ getViewTreeObserver().addOnPreDrawListener(listener);
return windowInsets;
});
@@ -98,7 +104,7 @@ class QtWindow extends QtLayout implements QtSurfaceInterface {
if (isAttachedToWindow()) {
WindowInsets insets = getRootWindowInsets();
if (insets != null) {
- safeAreaMarginsChanged(getSafeInsets(this, insets), getId());
+ getRootView().post(() -> reportSafeAreaMargins(insets, getId()));
m_firstSafeMarginsDelivered = true;
}
} else { // Otherwise request it upon attachement
@@ -128,7 +134,7 @@ class QtWindow extends QtLayout implements QtSurfaceInterface {
WindowInsets insets = getRootWindowInsets();
if (insets != null) {
getViewTreeObserver().removeOnPreDrawListener(this);
- safeAreaMarginsChanged(getSafeInsets(QtWindow.this, insets), getId());
+ getRootView().post(() -> reportSafeAreaMargins(insets, getId()));
m_firstSafeMarginsDelivered = true;
return true;
}
@@ -152,18 +158,10 @@ class QtWindow extends QtLayout implements QtSurfaceInterface {
}
// Android R and older
- int left = 0;
- int top = 0;
- int right = 0;
- int bottom = 0;
-
- int visibility = view.getSystemUiVisibility();
- if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
- left = insets.getSystemWindowInsetLeft();
- top = insets.getSystemWindowInsetTop();
- right = insets.getSystemWindowInsetRight();
- bottom = insets.getSystemWindowInsetBottom();
- }
+ int left = insets.getSystemWindowInsetLeft();
+ int top = insets.getSystemWindowInsetTop();
+ int right = insets.getSystemWindowInsetRight();
+ int bottom = insets.getSystemWindowInsetBottom();
// Android 9 and 10 emulators don't seem to be able
// to handle this, but let's have the logic here anyway
@@ -178,6 +176,36 @@ class QtWindow extends QtLayout implements QtSurfaceInterface {
return Insets.of(left, top, right, bottom);
}
+ private void reportSafeAreaMargins(WindowInsets insets, int id)
+ {
+ View rootView = getRootView();
+
+ int[] rootLocation = new int[2];
+ rootView.getLocationOnScreen(rootLocation);
+ int rootX = rootLocation[0];
+ int rootY = rootLocation[1];
+
+ int[] windowLocation = new int[2];
+ getLocationOnScreen(windowLocation);
+ int windowX = windowLocation[0];
+ int windowY = windowLocation[1];
+
+ // Offset values of window from root
+ int leftOffset = windowX - rootX;
+ int topOffset = windowY - rootY;
+ int rightOffset = (rootX + rootView.getWidth()) - (windowX + getWidth());
+ int bottomOffset = (rootY + rootView.getHeight()) - (windowY + getHeight());
+
+ // Find the remaining minimum safe margins
+ Insets safeInsets = getSafeInsets(this, insets);
+ int left = safeInsets.left > 0 ? Math.max(0, safeInsets.left - leftOffset) : 0;
+ int top = safeInsets.top > 0 ? Math.max(0, safeInsets.top - topOffset) : 0;
+ int right = safeInsets.right > 0 ? Math.max(0, safeInsets.right - rightOffset) : 0;
+ int bottom = safeInsets.bottom > 0 ? Math.max(0, safeInsets.bottom - bottomOffset) : 0;
+
+ safeAreaMarginsChanged(Insets.of(left, top, right, bottom), id);
+ }
+
@UsedFromNativeCode
void setVisible(boolean visible) {
QtNative.runAction(() -> setVisibility(visible ? View.VISIBLE : View.INVISIBLE));
diff --git a/src/plugins/platforms/android/qandroidplatformwindow.cpp b/src/plugins/platforms/android/qandroidplatformwindow.cpp
index 1989ecdee3c..de0271edb56 100644
--- a/src/plugins/platforms/android/qandroidplatformwindow.cpp
+++ b/src/plugins/platforms/android/qandroidplatformwindow.cpp
@@ -397,28 +397,33 @@ void QAndroidPlatformWindow::safeAreaMarginsChanged(JNIEnv *env, jobject object,
if (!qGuiApp)
return;
- QMargins safeMargins;
- if (insets.isValid()) {
- safeMargins = QMargins(
- insets.getField<int>("left"),
- insets.getField<int>("top"),
- insets.getField<int>("right"),
- insets.getField<int>("bottom"));
- }
+ if (!insets.isValid())
+ return;
+ QAndroidPlatformWindow *pWindow = nullptr;
for (QWindow *window : qGuiApp->allWindows()) {
if (!window->handle())
continue;
- QAndroidPlatformWindow *pWindow = static_cast<QAndroidPlatformWindow *>(window->handle());
- if (pWindow->nativeViewId() != id)
- continue;
-
- if (safeMargins != pWindow->safeAreaMargins()) {
- pWindow->setSafeAreaMargins(safeMargins);
- QWindowSystemInterface::handleSafeAreaMarginsChanged(window);
+ QAndroidPlatformWindow *pw = static_cast<QAndroidPlatformWindow *>(window->handle());
+ if (pw->nativeViewId() == id) {
+ pWindow = pw;
break;
}
}
+
+ if (!pWindow)
+ return;
+
+ QMargins safeMargins = QMargins(
+ insets.getField<int>("left"),
+ insets.getField<int>("top"),
+ insets.getField<int>("right"),
+ insets.getField<int>("bottom"));
+
+ if (safeMargins != pWindow->safeAreaMargins()) {
+ pWindow->setSafeAreaMargins(safeMargins);
+ QWindowSystemInterface::handleSafeAreaMarginsChanged(pWindow->window());
+ }
}
static void updateWindows(JNIEnv *env, jobject object)