iOS: Handle geometry of maximized windows outside of QIOSScreen
Ideally we would report the available geometry of our screen in a way that reflects the safe area margins of a potentially full screen window, but doing so requires that we manage UIWindows via QScreen/UIScreen, which is not in line with modern iOS window management. We still apply safe area margins to maximized windows, as before, but do so when applying the maximized state in QIOSWindow::setWindowState Task-number: QTBUG-121781 Change-Id: If7b9855aea47014f01e23dfe197b7057a1305a68 Reviewed-by: Amr Elsayed <amr.elsayed@qt.io> Reviewed-by: Doris Verria <doris.verria@qt.io>
This commit is contained in:
parent
eb9923c67e
commit
1a0c113b2d
@ -26,6 +26,7 @@ Q_DECLARE_LOGGING_CATEGORY(lcQpaWindow);
|
||||
class QPlatformScreen;
|
||||
|
||||
bool isQtApplication();
|
||||
bool isRunningOnVisionOS();
|
||||
|
||||
#ifndef Q_OS_TVOS
|
||||
Qt::ScreenOrientation toQtScreenOrientation(UIDeviceOrientation uiDeviceOrientation);
|
||||
|
@ -29,6 +29,15 @@ bool isQtApplication()
|
||||
return isQt;
|
||||
}
|
||||
|
||||
bool isRunningOnVisionOS()
|
||||
{
|
||||
static bool result = []{
|
||||
// This class is documented to only be available on visionOS
|
||||
return NSClassFromString(@"UIWindowSceneGeometryPreferencesVision");
|
||||
}();
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifndef Q_OS_TVOS
|
||||
Qt::ScreenOrientation toQtScreenOrientation(UIDeviceOrientation uiDeviceOrientation)
|
||||
{
|
||||
|
@ -310,15 +310,6 @@ QString QIOSScreen::name() const
|
||||
#endif
|
||||
}
|
||||
|
||||
[[maybe_unused]] static bool isRunningOnVisionOS()
|
||||
{
|
||||
static bool result = []{
|
||||
// This class is documented to only be available on visionOS
|
||||
return NSClassFromString(@"UIWindowSceneGeometryPreferencesVision");
|
||||
}();
|
||||
return result;
|
||||
}
|
||||
|
||||
void QIOSScreen::updateProperties()
|
||||
{
|
||||
QRect previousGeometry = m_geometry;
|
||||
@ -327,26 +318,9 @@ void QIOSScreen::updateProperties()
|
||||
#if defined(Q_OS_VISIONOS)
|
||||
// Based on what iPad app reports
|
||||
m_geometry = QRect(0, 0, 1194, 834);
|
||||
m_availableGeometry = m_geometry;
|
||||
m_depth = 24;
|
||||
#else
|
||||
m_geometry = QRectF::fromCGRect(m_uiScreen.bounds).toRect();
|
||||
m_availableGeometry = m_geometry;
|
||||
|
||||
// For convenience, we reflect the safe area margins of the screen's UIWindow
|
||||
// by reducing the available geometry of the screen. But we only do this if
|
||||
// the UIWindow bounds is representative of the UIScreen.
|
||||
if (isRunningOnVisionOS()) {
|
||||
// On visionOS there is no concept of a screen, and hence no concept of
|
||||
// screen-relative system UI that we should keep top level windows away
|
||||
// from, so don't apply the UIWindow safe area insets to the screen.
|
||||
} else {
|
||||
UIEdgeInsets safeAreaInsets = m_uiWindow.safeAreaInsets;
|
||||
if (m_uiWindow.bounds.size.width == m_uiScreen.bounds.size.width)
|
||||
m_availableGeometry.adjust(safeAreaInsets.left, 0, -safeAreaInsets.right, 0);
|
||||
if (m_uiWindow.bounds.size.height == m_uiScreen.bounds.size.height)
|
||||
m_availableGeometry.adjust(0, safeAreaInsets.top, 0, -safeAreaInsets.bottom);
|
||||
}
|
||||
|
||||
#ifndef Q_OS_TVOS
|
||||
if (m_uiScreen == [UIScreen mainScreen]) {
|
||||
@ -390,6 +364,12 @@ void QIOSScreen::updateProperties()
|
||||
|
||||
#endif // defined(Q_OS_VISIONOS)
|
||||
|
||||
// UIScreen does not provide a consistent accessor for the safe area margins
|
||||
// of the screen, and on visionOS we won't even have a UIScreen, so we report
|
||||
// the available geometry of the screen to be the same as the full geometry.
|
||||
// Safe area margins and maximized state is handled in QIOSWindow::setWindowState.
|
||||
m_availableGeometry = m_geometry;
|
||||
|
||||
// At construction time, we don't yet have an associated QScreen, but we still want
|
||||
// to compute the properties above so they are ready for when the QScreen attaches.
|
||||
// Also, at destruction time the QScreen has already been torn down, so notifying
|
||||
|
@ -261,21 +261,34 @@ void QIOSWindow::setWindowState(Qt::WindowStates state)
|
||||
// it to clamp the window geometry. Instead just use the UIWindow
|
||||
// directly, which represents our "screen".
|
||||
applyGeometry(uiWindowBounds);
|
||||
} else if (isRunningOnVisionOS()) {
|
||||
// On visionOS there is no concept of a screen, and hence no concept of
|
||||
// screen-relative system UI that we should keep top level windows away
|
||||
// from, so don't apply the UIWindow safe area insets to the screen.
|
||||
applyGeometry(uiWindowBounds);
|
||||
} else {
|
||||
// When an application is in split-view mode, the UIScreen still has the
|
||||
// same geometry, but the UIWindow is resized to the area reserved for the
|
||||
// application. We use this to constrain the geometry used when applying the
|
||||
// fullscreen or maximized window states. Note that we do not do this
|
||||
// in applyGeometry(), as we don't want to artificially limit window
|
||||
// placement "outside" of the screen bounds if that's what the user wants.
|
||||
QRect fullscreenGeometry = screen()->geometry().intersected(uiWindowBounds);
|
||||
QRect maximizedGeometry = window()->flags() & Qt::MaximizeUsingFullscreenGeometryHint ?
|
||||
fullscreenGeometry : screen()->availableGeometry().intersected(uiWindowBounds);
|
||||
QRect fullscreenGeometry = screen()->geometry();
|
||||
QRect maximizedGeometry = fullscreenGeometry;
|
||||
|
||||
#if !defined(Q_OS_VISIONOS)
|
||||
if (!(window()->flags() & Qt::MaximizeUsingFullscreenGeometryHint)) {
|
||||
// If the safe area margins reflect the screen's outer edges,
|
||||
// then reduce the maximized geometry accordingly. Otherwise
|
||||
// leave it as is, and assume the client will take the safe
|
||||
// are margins into account explicitly.
|
||||
UIScreen *uiScreen = m_view.window.windowScene.screen;
|
||||
UIEdgeInsets safeAreaInsets = m_view.window.safeAreaInsets;
|
||||
if (m_view.window.bounds.size.width == uiScreen.bounds.size.width)
|
||||
maximizedGeometry.adjust(safeAreaInsets.left, 0, -safeAreaInsets.right, 0);
|
||||
if (m_view.window.bounds.size.height == uiScreen.bounds.size.height)
|
||||
maximizedGeometry.adjust(0, safeAreaInsets.top, 0, -safeAreaInsets.bottom);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (state & Qt::WindowFullScreen)
|
||||
applyGeometry(fullscreenGeometry);
|
||||
applyGeometry(fullscreenGeometry.intersected(uiWindowBounds));
|
||||
else
|
||||
applyGeometry(maximizedGeometry);
|
||||
applyGeometry(maximizedGeometry.intersected(uiWindowBounds));
|
||||
}
|
||||
} else {
|
||||
applyGeometry(m_normalGeometry);
|
||||
|
Loading…
x
Reference in New Issue
Block a user