Android: consider DecorView insets at app startup
Set the initial safe area margins based on the decor view as a workaround since setOnApplyWindowInsetsListener() is not being called reliably at startups. This way we can get the app's initial insets at startup, then after that rely on each window reporting its insets. And apply this initial inset only for top level windows that match the screen size, i.e. we assume edge-to-edge is enable in that case. Task-number: QTBUG-135808 Fixes: QTBUG-135283 Fixes: QTBUG-135227 Change-Id: Ic5771809c94302b927ccc67ccc07c73ccc73b91d Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io> (cherry picked from commit e96a4b84e136d065054600c07bf5fae17f3049ce)
This commit is contained in:
parent
3a3c536c31
commit
1d014381f2
@ -75,47 +75,81 @@ class QtWindow extends QtLayout implements QtSurfaceInterface {
|
|||||||
});
|
});
|
||||||
m_gestureDetector.setIsLongpressEnabled(true);
|
m_gestureDetector.setIsLongpressEnabled(true);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (getContext() instanceof QtActivityBase) {
|
@UsedFromNativeCode
|
||||||
setOnApplyWindowInsetsListener((view, insets) -> {
|
void registerSafeAreaMarginsListner(boolean isTopLevel, boolean isSameWindowAndScreenSize)
|
||||||
Insets safeInsets;
|
{
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
if (!(getContext() instanceof QtActivityBase))
|
||||||
int types = WindowInsets.Type.displayCutout() | WindowInsets.Type.systemBars();
|
return;
|
||||||
safeInsets = insets.getInsets(types);
|
|
||||||
} else {
|
|
||||||
int left = 0;
|
|
||||||
int top = 0;
|
|
||||||
int right = 0;
|
|
||||||
int bottom = 0;
|
|
||||||
|
|
||||||
int visibility = view.getSystemUiVisibility();
|
setOnApplyWindowInsetsListener((view, insets) -> {
|
||||||
if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
|
Insets safeInsets = getSafeInsets(view, insets);
|
||||||
left = insets.getSystemWindowInsetLeft();
|
safeAreaMarginsChanged(safeInsets, getId());
|
||||||
top = insets.getSystemWindowInsetTop();
|
return getConsumedInsets(insets);
|
||||||
right = insets.getSystemWindowInsetRight();
|
});
|
||||||
bottom = insets.getSystemWindowInsetBottom();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Android 9 and 10 emulators don't seem to be able
|
// NOTE: if the window size fits the screen geometry (i.e. edge-to-edge case),
|
||||||
// to handle this, but let's have the logic here anyway
|
// assume this window is the main window and initialize its safe margins with
|
||||||
DisplayCutout cutout = insets.getDisplayCutout();
|
// the insets of the decor view.
|
||||||
if (cutout != null) {
|
if (isTopLevel && isSameWindowAndScreenSize) {
|
||||||
left = Math.max(left, cutout.getSafeInsetLeft());
|
QtNative.runAction(() -> {
|
||||||
top = Math.max(top, cutout.getSafeInsetTop());
|
// NOTE: The callback onApplyWindowInsetsListener() is not being triggered during
|
||||||
right = Math.max(right, cutout.getSafeInsetRight());
|
// startup, so this is a Workaround to get the safe area margins at startup.
|
||||||
bottom = Math.max(bottom, cutout.getSafeInsetBottom());
|
// 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();
|
||||||
safeInsets = Insets.of(left, top, right, bottom);
|
WindowInsets rootInsets = decorView.getRootWindowInsets();
|
||||||
}
|
Insets rootSafeInsets = getSafeInsets(decorView, rootInsets);
|
||||||
|
safeAreaMarginsChanged(rootSafeInsets, getId());
|
||||||
QtNative.runAction(() -> safeAreaMarginsChanged(safeInsets, getId()));
|
|
||||||
|
|
||||||
return insets;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
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
|
@UsedFromNativeCode
|
||||||
|
@ -96,6 +96,11 @@ void QAndroidPlatformWindow::initialize()
|
|||||||
}
|
}
|
||||||
qCDebug(lcQpaWindow) << "Window" << m_nativeViewId << "using surface container type"
|
qCDebug(lcQpaWindow) << "Window" << m_nativeViewId << "using surface container type"
|
||||||
<< static_cast<int>(m_surfaceContainerType);
|
<< static_cast<int>(m_surfaceContainerType);
|
||||||
|
|
||||||
|
const bool isSameWindowAndScreenSize = geometry().size() == screen()->geometry().size();
|
||||||
|
m_nativeQtWindow.callMethod<void>("registerSafeAreaMarginsListner",
|
||||||
|
window->isTopLevel(), isSameWindowAndScreenSize);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QAndroidPlatformWindow::~QAndroidPlatformWindow()
|
QAndroidPlatformWindow::~QAndroidPlatformWindow()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user