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 4bd5300bd76..1f5ae6c2ad9 100644 --- a/src/android/jar/src/org/qtproject/qt/android/QtWindow.java +++ b/src/android/jar/src/org/qtproject/qt/android/QtWindow.java @@ -75,47 +75,81 @@ class QtWindow extends QtLayout implements QtSurfaceInterface { }); m_gestureDetector.setIsLongpressEnabled(true); }); + } - if (getContext() instanceof QtActivityBase) { - setOnApplyWindowInsetsListener((view, insets) -> { - Insets safeInsets; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - int types = WindowInsets.Type.displayCutout() | WindowInsets.Type.systemBars(); - safeInsets = insets.getInsets(types); - } else { - int left = 0; - int top = 0; - int right = 0; - int bottom = 0; + @UsedFromNativeCode + void registerSafeAreaMarginsListner(boolean isTopLevel, boolean isSameWindowAndScreenSize) + { + if (!(getContext() instanceof QtActivityBase)) + return; - int visibility = view.getSystemUiVisibility(); - if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) { - left = insets.getSystemWindowInsetLeft(); - top = insets.getSystemWindowInsetTop(); - right = insets.getSystemWindowInsetRight(); - bottom = insets.getSystemWindowInsetBottom(); - } + setOnApplyWindowInsetsListener((view, insets) -> { + Insets safeInsets = getSafeInsets(view, insets); + safeAreaMarginsChanged(safeInsets, getId()); + return getConsumedInsets(insets); + }); - // Android 9 and 10 emulators don't seem to be able - // to handle this, but let's have the logic here anyway - DisplayCutout cutout = insets.getDisplayCutout(); - if (cutout != null) { - left = Math.max(left, cutout.getSafeInsetLeft()); - top = Math.max(top, cutout.getSafeInsetTop()); - right = Math.max(right, cutout.getSafeInsetRight()); - bottom = Math.max(bottom, cutout.getSafeInsetBottom()); - } - - safeInsets = Insets.of(left, top, right, bottom); - } - - QtNative.runAction(() -> safeAreaMarginsChanged(safeInsets, getId())); - - return insets; + // NOTE: if the window size fits the screen geometry (i.e. edge-to-edge case), + // assume this window is the main window and initialize its safe margins with + // the insets of the decor view. + if (isTopLevel && isSameWindowAndScreenSize) { + QtNative.runAction(() -> { + // NOTE: The callback onApplyWindowInsetsListener() is not being triggered during + // startup, so this is a Workaround to get the safe area margins at startup. + // Initially, set the root view insets to the current window, then if the insets + // change later, we can rely on setOnApplyWindowInsetsListener() being called. + View decorView = ((Activity) getContext()).getWindow().getDecorView(); + WindowInsets rootInsets = decorView.getRootWindowInsets(); + Insets rootSafeInsets = getSafeInsets(decorView, rootInsets); + safeAreaMarginsChanged(rootSafeInsets, getId()); }); - - QtNative.runAction(() -> requestApplyInsets()); } + + QtNative.runAction(() -> requestApplyInsets()); + } + + @SuppressWarnings("deprecation") + WindowInsets getConsumedInsets(WindowInsets insets) + { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) + return WindowInsets.CONSUMED; + else + return insets.consumeSystemWindowInsets(); + } + + @SuppressWarnings("deprecation") + Insets getSafeInsets(View view, WindowInsets insets) + { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + int types = WindowInsets.Type.displayCutout() | WindowInsets.Type.systemBars(); + return insets.getInsets(types); + } + + // 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(); + } + + // Android 9 and 10 emulators don't seem to be able + // to handle this, but let's have the logic here anyway + DisplayCutout cutout = insets.getDisplayCutout(); + if (cutout != null) { + left = Math.max(left, cutout.getSafeInsetLeft()); + top = Math.max(top, cutout.getSafeInsetTop()); + right = Math.max(right, cutout.getSafeInsetRight()); + bottom = Math.max(bottom, cutout.getSafeInsetBottom()); + } + + return Insets.of(left, top, right, bottom); } @UsedFromNativeCode diff --git a/src/plugins/platforms/android/qandroidplatformwindow.cpp b/src/plugins/platforms/android/qandroidplatformwindow.cpp index e22f336bc51..e904145a7c9 100644 --- a/src/plugins/platforms/android/qandroidplatformwindow.cpp +++ b/src/plugins/platforms/android/qandroidplatformwindow.cpp @@ -96,6 +96,11 @@ void QAndroidPlatformWindow::initialize() } qCDebug(lcQpaWindow) << "Window" << m_nativeViewId << "using surface container type" << static_cast(m_surfaceContainerType); + + const bool isSameWindowAndScreenSize = geometry().size() == screen()->geometry().size(); + m_nativeQtWindow.callMethod("registerSafeAreaMarginsListner", + window->isTopLevel(), isSameWindowAndScreenSize); + } QAndroidPlatformWindow::~QAndroidPlatformWindow()