diff options
| author | Assam Boudjelthia <assam.boudjelthia@qt.io> | 2025-08-30 04:59:52 +0300 |
|---|---|---|
| committer | Assam Boudjelthia <assam.boudjelthia@qt.io> | 2025-09-06 01:27:38 +0300 |
| commit | e2a9ab46d39d442b198fe77d13153b8fc6b64a35 (patch) | |
| tree | 381642a97e1c2ccb742034e252b31b0ae4073813 /src | |
| parent | 357580c2253b2e1e5c09170a249cc59b2da30677 (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.java | 62 | ||||
| -rw-r--r-- | src/plugins/platforms/android/qandroidplatformwindow.cpp | 35 |
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) |
