summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/ios/qioswindow.mm
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/ios/qioswindow.mm')
-rw-r--r--src/plugins/platforms/ios/qioswindow.mm110
1 files changed, 61 insertions, 49 deletions
diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm
index 3631d6be70..7cd3d5f0b0 100644
--- a/src/plugins/platforms/ios/qioswindow.mm
+++ b/src/plugins/platforms/ios/qioswindow.mm
@@ -21,7 +21,7 @@
#import <QuartzCore/CAEAGLLayer.h>
#endif
-#ifdef Q_OS_IOS
+#if QT_CONFIG(metal)
#import <QuartzCore/CAMetalLayer.h>
#endif
@@ -36,13 +36,12 @@ enum {
QIOSWindow::QIOSWindow(QWindow *window, WId nativeHandle)
: QPlatformWindow(window)
- , m_windowLevel(0)
{
if (nativeHandle) {
m_view = reinterpret_cast<UIView *>(nativeHandle);
[m_view retain];
} else {
-#ifdef Q_OS_IOS
+#if QT_CONFIG(metal)
if (window->surfaceType() == QSurface::RasterSurface)
window->setSurfaceType(QSurface::MetalSurface);
@@ -55,6 +54,9 @@ QIOSWindow::QIOSWindow(QWindow *window, WId nativeHandle)
connect(qGuiApp, &QGuiApplication::applicationStateChanged, this, &QIOSWindow::applicationStateChanged);
+ // Always set parent, even if we don't have a parent window,
+ // as we use setParent to reparent top levels into our desktop
+ // manager view.
setParent(QPlatformWindow::parent());
if (!isForeignWindow()) {
@@ -124,11 +126,6 @@ void QIOSWindow::setVisible(bool visible)
if (!isQtApplication() || !window()->isTopLevel())
return;
- // Since iOS doesn't do window management the way a Qt application
- // expects, we need to raise and activate windows ourselves:
- if (visible)
- updateWindowLevel();
-
if (blockedByModal()) {
if (visible)
raise();
@@ -261,21 +258,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);
@@ -284,14 +294,14 @@ void QIOSWindow::setWindowState(Qt::WindowStates state)
void QIOSWindow::setParent(const QPlatformWindow *parentWindow)
{
- UIView *parentView = parentWindow ?
- reinterpret_cast<UIView *>(parentWindow->winId())
- : isQtApplication() && !isForeignWindow() ?
- static_cast<QIOSScreen *>(screen())->uiWindow().rootViewController.view
- : nullptr;
-
- if (parentView)
- [parentView addSubview:m_view];
+ UIView *superview = nullptr;
+ if (parentWindow)
+ superview = reinterpret_cast<UIView *>(parentWindow->winId());
+ else if (isQtApplication() && !isForeignWindow())
+ superview = rootViewForScreen(window()->screen());
+
+ if (superview)
+ [superview addSubview:m_view];
else if (quiview_cast(m_view.superview))
[m_view removeFromSuperview];
}
@@ -304,7 +314,6 @@ void QIOSWindow::requestActivateWindow()
if (blockedByModal())
return;
- Q_ASSERT(m_view.window);
[m_view.window makeKeyWindow];
[m_view becomeFirstResponder];
@@ -328,8 +337,8 @@ void QIOSWindow::raiseOrLower(bool raise)
UIView *view = static_cast<UIView *>([subviews objectAtIndex:i]);
if (view.hidden || view == m_view || !view.qwindow)
continue;
- int level = static_cast<QIOSWindow *>(view.qwindow->handle())->m_windowLevel;
- if (m_windowLevel > level || (raise && m_windowLevel == level)) {
+ int level = static_cast<QIOSWindow *>(view.qwindow->handle())->windowLevel();
+ if (windowLevel() > level || (raise && windowLevel() == level)) {
[m_view.superview insertSubview:m_view aboveSubview:view];
return;
}
@@ -344,40 +353,34 @@ void QIOSWindow::raiseOrLower(bool raise)
}
}
-void QIOSWindow::updateWindowLevel()
+int QIOSWindow::windowLevel() const
{
Qt::WindowType type = window()->type();
+ int level = 0;
+
if (type == Qt::ToolTip)
- m_windowLevel = 120;
+ level = 120;
else if (window()->flags() & Qt::WindowStaysOnTopHint)
- m_windowLevel = 100;
+ level = 100;
else if (window()->isModal())
- m_windowLevel = 40;
+ level = 40;
else if (type == Qt::Popup)
- m_windowLevel = 30;
+ level = 30;
else if (type == Qt::SplashScreen)
- m_windowLevel = 20;
+ level = 20;
else if (type == Qt::Tool)
- m_windowLevel = 10;
+ level = 10;
else
- m_windowLevel = 0;
+ level = 0;
- // A window should be in at least the same m_windowLevel as its parent:
+ // A window should be in at least the same window level as its parent
QWindow *transientParent = window()->transientParent();
QIOSWindow *transientParentWindow = transientParent ? static_cast<QIOSWindow *>(transientParent->handle()) : 0;
if (transientParentWindow)
- m_windowLevel = qMax(transientParentWindow->m_windowLevel, m_windowLevel);
-}
+ level = qMax(transientParentWindow->windowLevel(), level);
-void QIOSWindow::handleContentOrientationChange(Qt::ScreenOrientation orientation)
-{
- // Update the QWindow representation straight away, so that
- // we can update the statusbar orientation based on the new
- // content orientation.
- qt_window_private(window())->contentOrientation = orientation;
-
- [m_view.qtViewController updateProperties];
+ return level;
}
void QIOSWindow::applicationStateChanged(Qt::ApplicationState)
@@ -391,6 +394,15 @@ void QIOSWindow::applicationStateChanged(Qt::ApplicationState)
qreal QIOSWindow::devicePixelRatio() const
{
+#if !defined(Q_OS_VISIONOS)
+ // If the view has not yet been added to a screen, it will not
+ // pick up its device pixel ratio, so we need to do so manually
+ // based on the screen we think the window will be added to.
+ if (!m_view.window.windowScene.screen)
+ return screen()->devicePixelRatio();
+#endif
+
+ // Otherwise we can rely on the content scale factor
return m_view.contentScaleFactor;
}