summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/ios
diff options
context:
space:
mode:
authorTor Arne Vestbø <tor.arne.vestbo@qt.io>2024-03-18 19:35:52 +0100
committerTor Arne Vestbø <tor.arne.vestbo@qt.io>2024-04-18 05:00:57 +0200
commitd5bf42f75b0ae35b7f02bb9211787ae1d44a98ba (patch)
tree3aa389137752dbe2bbaa7446e4ef0e2e1b8c55a5 /src/plugins/platforms/ios
parentbf2ed624091d0239bce91a84df59b7afc843298a (diff)
Add preliminary support for Qt for visionOS
Qt already runs on Vision Pro as "Designed for iPad", using Qt for iOS. This change enables building Qt for visionOS directly, which opens the door to visionOS specific APIs and use-cases such as volumes and immersive spaces. The platform removes some APIs we depend on, notably UIScreen, so some code paths have been disabled or mocked to get something up and running. As our current window management approach on UIKit platforms depends on UIWindow and UIScreen there is currently no way to bring up QWindows. This will improve once we refactor our window management to use window scenes. To configure for visionOS, pass -platform macx-visionos-clang, and optionally add -sdk xrsimulator to build for the simulator. Change-Id: I4eda55fc3fd06e12d30a188928487cf68940ee07 Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
Diffstat (limited to 'src/plugins/platforms/ios')
-rw-r--r--src/plugins/platforms/ios/CMakeLists.txt25
-rw-r--r--src/plugins/platforms/ios/qioscolordialog.mm4
-rw-r--r--src/plugins/platforms/ios/qiosfiledialog.mm7
-rw-r--r--src/plugins/platforms/ios/qiosfontdialog.mm4
-rw-r--r--src/plugins/platforms/ios/qiosglobal.h3
-rw-r--r--src/plugins/platforms/ios/qiosglobal.mm10
-rw-r--r--src/plugins/platforms/ios/qiosinputcontext.mm6
-rw-r--r--src/plugins/platforms/ios/qiosintegration.h11
-rw-r--r--src/plugins/platforms/ios/qiosintegration.mm19
-rw-r--r--src/plugins/platforms/ios/qiosmessagedialog.mm2
-rw-r--r--src/plugins/platforms/ios/qiosscreen.h18
-rw-r--r--src/plugins/platforms/ios/qiosscreen.mm54
-rw-r--r--src/plugins/platforms/ios/qiostextresponder.mm2
-rw-r--r--src/plugins/platforms/ios/qiostheme.h2
-rw-r--r--src/plugins/platforms/ios/qiostheme.mm29
-rw-r--r--src/plugins/platforms/ios/qiosviewcontroller.mm14
-rw-r--r--src/plugins/platforms/ios/qioswindow.mm5
-rw-r--r--src/plugins/platforms/ios/quiview.h2
-rw-r--r--src/plugins/platforms/ios/quiview.mm10
19 files changed, 161 insertions, 66 deletions
diff --git a/src/plugins/platforms/ios/CMakeLists.txt b/src/plugins/platforms/ios/CMakeLists.txt
index 1c99103a49..32e4eb8051 100644
--- a/src/plugins/platforms/ios/CMakeLists.txt
+++ b/src/plugins/platforms/ios/CMakeLists.txt
@@ -57,20 +57,31 @@ qt_internal_extend_target(QIOSIntegrationPlugin CONDITION QT_FEATURE_opengl
Qt::OpenGLPrivate
)
-qt_internal_extend_target(QIOSIntegrationPlugin CONDITION NOT TVOS
+qt_internal_extend_target(QIOSIntegrationPlugin CONDITION QT_FEATURE_clipboard
SOURCES
qiosclipboard.h qiosclipboard.mm
- qiosdocumentpickercontroller.h qiosdocumentpickercontroller.mm
+)
+
+qt_internal_extend_target(QIOSIntegrationPlugin CONDITION NOT TVOS
+ SOURCES
qiosfiledialog.h qiosfiledialog.mm
+ qiosdocumentpickercontroller.h qiosdocumentpickercontroller.mm
+ LIBRARIES
+ ${FWUniformTypeIdentifiers}
+ ${FWPhotos}
+)
+
+qt_internal_extend_target(QIOSIntegrationPlugin CONDITION NOT TVOS
+ SOURCES
qioscolordialog.h qioscolordialog.mm
qiosfontdialog.h qiosfontdialog.mm
- qiosmenu.h qiosmenu.mm
qiosmessagedialog.h qiosmessagedialog.mm
+)
+
+qt_internal_extend_target(QIOSIntegrationPlugin CONDITION NOT (TVOS OR VISIONOS)
+ SOURCES
+ qiosmenu.h qiosmenu.mm
qiostextinputoverlay.h qiostextinputoverlay.mm
- LIBRARIES
- ${FWAssetsLibrary}
- ${FWUniformTypeIdentifiers}
- ${FWPhotos}
)
add_subdirectory(optional)
diff --git a/src/plugins/platforms/ios/qioscolordialog.mm b/src/plugins/platforms/ios/qioscolordialog.mm
index 92c0f3e46c..6651b1791d 100644
--- a/src/plugins/platforms/ios/qioscolordialog.mm
+++ b/src/plugins/platforms/ios/qioscolordialog.mm
@@ -8,6 +8,7 @@
#include <QtCore/private/qcore_mac_p.h>
+#include "qiosglobal.h"
#include "qioscolordialog.h"
#include "qiosintegration.h"
@@ -117,8 +118,7 @@ bool QIOSColorDialog::show(Qt::WindowFlags windowFlags, Qt::WindowModality windo
if (windowModality == Qt::ApplicationModal || windowModality == Qt::WindowModal)
m_viewController.modalInPresentation = YES;
- UIWindow *window = parent ? reinterpret_cast<UIView *>(parent->winId()).window
- : qt_apple_sharedApplication().keyWindow;
+ UIWindow *window = presentationWindow(parent);
if (!window)
return false;
diff --git a/src/plugins/platforms/ios/qiosfiledialog.mm b/src/plugins/platforms/ios/qiosfiledialog.mm
index 63d180220b..cf9580c17e 100644
--- a/src/plugins/platforms/ios/qiosfiledialog.mm
+++ b/src/plugins/platforms/ios/qiosfiledialog.mm
@@ -11,6 +11,7 @@
#include <QtCore/private/qcore_mac_p.h>
+#include "qiosglobal.h"
#include "qiosfiledialog.h"
#include "qiosintegration.h"
#include "qiosoptionalplugininterface.h"
@@ -59,8 +60,7 @@ bool QIOSFileDialog::show(Qt::WindowFlags windowFlags, Qt::WindowModality window
void QIOSFileDialog::showImagePickerDialog_helper(QWindow *parent)
{
- UIWindow *window = parent ? reinterpret_cast<UIView *>(parent->winId()).window
- : qt_apple_sharedApplication().keyWindow;
+ UIWindow *window = presentationWindow(parent);
[window.rootViewController presentViewController:m_viewController animated:YES completion:nil];
}
@@ -123,8 +123,7 @@ bool QIOSFileDialog::showNativeDocumentPickerDialog(QWindow *parent)
#ifndef Q_OS_TVOS
m_viewController = [[QIOSDocumentPickerController alloc] initWithQIOSFileDialog:this];
- UIWindow *window = parent ? reinterpret_cast<UIView *>(parent->winId()).window
- : qt_apple_sharedApplication().keyWindow;
+ UIWindow *window = presentationWindow(parent);
[window.rootViewController presentViewController:m_viewController animated:YES completion:nil];
return true;
diff --git a/src/plugins/platforms/ios/qiosfontdialog.mm b/src/plugins/platforms/ios/qiosfontdialog.mm
index 4cea1cb558..25d0197195 100644
--- a/src/plugins/platforms/ios/qiosfontdialog.mm
+++ b/src/plugins/platforms/ios/qiosfontdialog.mm
@@ -11,6 +11,7 @@
#include <QtGui/private/qfont_p.h>
#include <QtGui/private/qfontengine_p.h>
+#include "qiosglobal.h"
#include "qiosfontdialog.h"
#include "qiosintegration.h"
@@ -144,8 +145,7 @@ bool QIOSFontDialog::show(Qt::WindowFlags windowFlags, Qt::WindowModality window
if (windowModality == Qt::ApplicationModal || windowModality == Qt::WindowModal)
m_viewController.modalInPresentation = YES;
- UIWindow *window = parent ? reinterpret_cast<UIView *>(parent->winId()).window
- : qt_apple_sharedApplication().keyWindow;
+ UIWindow *window = presentationWindow(parent);
if (!window)
return false;
diff --git a/src/plugins/platforms/ios/qiosglobal.h b/src/plugins/platforms/ios/qiosglobal.h
index a5139a3fde..e7ca2d1fec 100644
--- a/src/plugins/platforms/ios/qiosglobal.h
+++ b/src/plugins/platforms/ios/qiosglobal.h
@@ -34,6 +34,9 @@ UIDeviceOrientation fromQtScreenOrientation(Qt::ScreenOrientation qtOrientation)
int infoPlistValue(NSString* key, int defaultValue);
+class QWindow;
+UIWindow *presentationWindow(QWindow *);
+
QT_END_NAMESPACE
@interface UIResponder (QtFirstResponder)
diff --git a/src/plugins/platforms/ios/qiosglobal.mm b/src/plugins/platforms/ios/qiosglobal.mm
index c0faccaf71..169c292a00 100644
--- a/src/plugins/platforms/ios/qiosglobal.mm
+++ b/src/plugins/platforms/ios/qiosglobal.mm
@@ -85,6 +85,16 @@ int infoPlistValue(NSString* key, int defaultValue)
return value ? [value intValue] : defaultValue;
}
+UIWindow *presentationWindow(QWindow *window)
+{
+ UIWindow *uiWindow = window ? reinterpret_cast<UIView *>(window->winId()).window : nullptr;
+#if !defined(Q_OS_VISIONOS)
+ if (!uiWindow)
+ uiWindow = qt_apple_sharedApplication().keyWindow;
+#endif
+ return uiWindow;
+}
+
QT_END_NAMESPACE
// -------------------------------------------------------------------------
diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm
index 56322a0f65..d4f81f22e3 100644
--- a/src/plugins/platforms/ios/qiosinputcontext.mm
+++ b/src/plugins/platforms/ios/qiosinputcontext.mm
@@ -22,11 +22,13 @@
// -------------------------------------------------------------------------
+#if !defined(Q_OS_VISIONOS)
static QUIView *focusView()
{
return qApp->focusWindow() ?
reinterpret_cast<QUIView *>(qApp->focusWindow()->winId()) : 0;
}
+#endif
// -------------------------------------------------------------------------
@@ -352,7 +354,7 @@ void QIOSInputContext::clearCurrentFocusObject()
void QIOSInputContext::updateKeyboardState(NSNotification *notification)
{
-#ifdef Q_OS_TVOS
+#if defined(Q_OS_TVOS) || defined(Q_OS_VISIONOS)
Q_UNUSED(notification);
#else
static CGRect currentKeyboardRect = CGRectZero;
@@ -442,6 +444,7 @@ UIView *QIOSInputContext::scrollableRootView()
void QIOSInputContext::scrollToCursor()
{
+#if !defined(Q_OS_VISIONOS)
if (!isQtApplication())
return;
@@ -498,6 +501,7 @@ void QIOSInputContext::scrollToCursor()
} else {
scroll(0);
}
+#endif
}
void QIOSInputContext::scroll(int y)
diff --git a/src/plugins/platforms/ios/qiosintegration.h b/src/plugins/platforms/ios/qiosintegration.h
index a57a707c7f..2c7d33cc94 100644
--- a/src/plugins/platforms/ios/qiosintegration.h
+++ b/src/plugins/platforms/ios/qiosintegration.h
@@ -11,7 +11,8 @@
#include <QtCore/private/qfactoryloader_p.h>
#include "qiosapplicationstate.h"
-#ifndef Q_OS_TVOS
+
+#if !defined(Q_OS_TVOS) && !defined(Q_OS_VISIONOS)
#include "qiostextinputoverlay.h"
#endif
@@ -41,9 +42,11 @@ public:
QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const override;
QPlatformFontDatabase *fontDatabase() const override;
-#ifndef QT_NO_CLIPBOARD
+
+#if QT_CONFIG(clipboard)
QPlatformClipboard *clipboard() const override;
#endif
+
QPlatformInputContext *inputContext() const override;
QPlatformServices *services() const override;
@@ -76,7 +79,7 @@ public:
private:
QPlatformFontDatabase *m_fontDatabase;
-#ifndef Q_OS_TVOS
+#if QT_CONFIG(clipboard)
QPlatformClipboard *m_clipboard;
#endif
QPlatformInputContext *m_inputContext;
@@ -84,7 +87,7 @@ private:
QIOSServices *m_platformServices;
mutable QPlatformAccessibility *m_accessibility;
QFactoryLoader *m_optionalPlugins;
-#ifndef Q_OS_TVOS
+#if !defined(Q_OS_TVOS) && !defined(Q_OS_VISIONOS)
QIOSTextInputOverlay m_textInputOverlay;
#endif
};
diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm
index c646042eb2..7cd21f83f6 100644
--- a/src/plugins/platforms/ios/qiosintegration.mm
+++ b/src/plugins/platforms/ios/qiosintegration.mm
@@ -9,7 +9,7 @@
#include "qioswindow.h"
#include "qiosscreen.h"
#include "qiosplatformaccessibility.h"
-#ifndef Q_OS_TVOS
+#if QT_CONFIG(clipboard)
#include "qiosclipboard.h"
#endif
#include "qiosinputcontext.h"
@@ -51,7 +51,7 @@ QIOSIntegration *QIOSIntegration::instance()
QIOSIntegration::QIOSIntegration()
: m_fontDatabase(new QCoreTextFontDatabaseEngineFactory<QCoreTextFontEngine>)
-#if !defined(Q_OS_TVOS) && !defined(QT_NO_CLIPBOARD)
+#if QT_CONFIG(clipboard)
, m_clipboard(new QIOSClipboard)
#endif
, m_inputContext(0)
@@ -72,6 +72,10 @@ QIOSIntegration::QIOSIntegration()
void QIOSIntegration::initialize()
{
+#if defined(Q_OS_VISIONOS)
+ // Qt requires a screen, so let's give it a dummy one
+ QWindowSystemInterface::handleScreenAdded(new QIOSScreen);
+#else
UIScreen *mainScreen = [UIScreen mainScreen];
NSMutableArray<UIScreen *> *screens = [[[UIScreen screens] mutableCopy] autorelease];
if (![screens containsObject:mainScreen]) {
@@ -81,6 +85,7 @@ void QIOSIntegration::initialize()
for (UIScreen *screen in screens)
QWindowSystemInterface::handleScreenAdded(new QIOSScreen(screen));
+#endif
// Depends on a primary screen being present
m_inputContext = new QIOSInputContext;
@@ -88,8 +93,10 @@ void QIOSIntegration::initialize()
m_touchDevice = new QPointingDevice;
m_touchDevice->setType(QInputDevice::DeviceType::TouchScreen);
QPointingDevice::Capabilities touchCapabilities = QPointingDevice::Capability::Position | QPointingDevice::Capability::NormalizedPosition;
+#if !defined(Q_OS_VISIONOS)
if (mainScreen.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable)
touchCapabilities |= QPointingDevice::Capability::Pressure;
+#endif
m_touchDevice->setCapabilities(touchCapabilities);
QWindowSystemInterface::registerInputDevice(m_touchDevice);
#if QT_CONFIG(tabletevent)
@@ -107,7 +114,7 @@ QIOSIntegration::~QIOSIntegration()
delete m_fontDatabase;
m_fontDatabase = 0;
-#if !defined(Q_OS_TVOS) && !defined(QT_NO_CLIPBOARD)
+#if QT_CONFIG(clipboard)
delete m_clipboard;
m_clipboard = 0;
#endif
@@ -208,14 +215,10 @@ QPlatformFontDatabase * QIOSIntegration::fontDatabase() const
return m_fontDatabase;
}
-#ifndef QT_NO_CLIPBOARD
+#if QT_CONFIG(clipboard)
QPlatformClipboard *QIOSIntegration::clipboard() const
{
-#ifndef Q_OS_TVOS
return m_clipboard;
-#else
- return QPlatformIntegration::clipboard();
-#endif
}
#endif
diff --git a/src/plugins/platforms/ios/qiosmessagedialog.mm b/src/plugins/platforms/ios/qiosmessagedialog.mm
index 34421bbbd1..979829377a 100644
--- a/src/plugins/platforms/ios/qiosmessagedialog.mm
+++ b/src/plugins/platforms/ios/qiosmessagedialog.mm
@@ -116,7 +116,7 @@ bool QIOSMessageDialog::show(Qt::WindowFlags windowFlags, Qt::WindowModality win
[m_alertController addAction:createAction(NoButton)];
}
- UIWindow *window = parent ? reinterpret_cast<UIView *>(parent->winId()).window : qt_apple_sharedApplication().keyWindow;
+ UIWindow *window = presentationWindow(parent);
if (!window) {
qCDebug(lcQpaWindow, "Attempting to exec a dialog without any window/widget visible.");
diff --git a/src/plugins/platforms/ios/qiosscreen.h b/src/plugins/platforms/ios/qiosscreen.h
index 21afb90c55..b1fa5cad0d 100644
--- a/src/plugins/platforms/ios/qiosscreen.h
+++ b/src/plugins/platforms/ios/qiosscreen.h
@@ -21,7 +21,11 @@ class QIOSScreen : public QObject, public QPlatformScreen
Q_OBJECT
public:
+#if !defined(Q_OS_VISIONOS)
QIOSScreen(UIScreen *screen);
+#else
+ QIOSScreen();
+#endif
~QIOSScreen();
QString name() const override;
@@ -40,7 +44,9 @@ public:
QPixmap grabWindow(WId window, int x, int y, int width, int height) const override;
+#if !defined(Q_OS_VISIONOS)
UIScreen *uiScreen() const;
+#endif
UIWindow *uiWindow() const;
void setUpdatesPaused(bool);
@@ -50,15 +56,19 @@ public:
private:
void deliverUpdateRequests() const;
- UIScreen *m_uiScreen;
- UIWindow *m_uiWindow;
+#if !defined(Q_OS_VISIONOS)
+ UIScreen *m_uiScreen = nullptr;
+#endif
+ UIWindow *m_uiWindow = nullptr;
QRect m_geometry;
QRect m_availableGeometry;
int m_depth;
+#if !defined(Q_OS_VISIONOS)
uint m_physicalDpi;
+#endif
QSizeF m_physicalSize;
- QIOSOrientationListener *m_orientationListener;
- CADisplayLink *m_displayLink;
+ QIOSOrientationListener *m_orientationListener = nullptr;
+ CADisplayLink *m_displayLink = nullptr;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm
index e48592aa24..5c61f6f724 100644
--- a/src/plugins/platforms/ios/qiosscreen.mm
+++ b/src/plugins/platforms/ios/qiosscreen.mm
@@ -46,6 +46,7 @@ typedef void (^DisplayLinkBlock)(CADisplayLink *displayLink);
// -------------------------------------------------------------------------
+#if !defined(Q_OS_VISIONOS)
static QIOSScreen* qtPlatformScreenFor(UIScreen *uiScreen)
{
foreach (QScreen *screen, QGuiApplication::screens()) {
@@ -149,6 +150,8 @@ static QIOSScreen* qtPlatformScreenFor(UIScreen *uiScreen)
@end
+#endif // !defined(Q_OS_VISIONOS)
+
// -------------------------------------------------------------------------
@implementation QUIWindow
@@ -167,6 +170,7 @@ static QIOSScreen* qtPlatformScreenFor(UIScreen *uiScreen)
[super sendEvent:event];
}
+#if !defined(Q_OS_VISIONOS)
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection
{
[super traitCollectionDidChange:previousTraitCollection];
@@ -189,6 +193,7 @@ static QIOSScreen* qtPlatformScreenFor(UIScreen *uiScreen)
}
}
}
+#endif
@end
@@ -198,6 +203,7 @@ QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals;
+#if !defined(Q_OS_VISIONOS)
/*!
Returns the model identifier of the device.
*/
@@ -217,12 +223,14 @@ static QString deviceModelIdentifier()
return QString::fromLatin1(QByteArrayView(value, qsizetype(size)));
#endif
}
+#endif // !defined(Q_OS_VISIONOS)
+#if defined(Q_OS_VISIONOS)
+QIOSScreen::QIOSScreen()
+{
+#else
QIOSScreen::QIOSScreen(UIScreen *screen)
- : QPlatformScreen()
- , m_uiScreen(screen)
- , m_uiWindow(0)
- , m_orientationListener(0)
+ : m_uiScreen(screen)
{
QString deviceIdentifier = deviceModelIdentifier();
@@ -273,11 +281,13 @@ QIOSScreen::QIOSScreen(UIScreen *screen)
m_orientationListener = [[QIOSOrientationListener alloc] initWithQIOSScreen:this];
- updateProperties();
-
m_displayLink = [m_uiScreen displayLinkWithBlock:^(CADisplayLink *) { deliverUpdateRequests(); }];
m_displayLink.paused = YES; // Enabled when clients call QWindow::requestUpdate()
[m_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
+
+#endif // !defined(Q_OS_VISIONOS))
+
+ updateProperties();
}
QIOSScreen::~QIOSScreen()
@@ -290,13 +300,17 @@ QIOSScreen::~QIOSScreen()
QString QIOSScreen::name() const
{
+#if defined(Q_OS_VISIONOS)
+ return {};
+#else
if (m_uiScreen == [UIScreen mainScreen])
return QString::fromNSString([UIDevice currentDevice].model) + " built-in display"_L1;
else
return "External display"_L1;
+#endif
}
-static bool isRunningOnVisionOS()
+[[maybe_unused]] static bool isRunningOnVisionOS()
{
static bool result = []{
// This class is documented to only be available on visionOS
@@ -310,8 +324,13 @@ void QIOSScreen::updateProperties()
QRect previousGeometry = m_geometry;
QRect previousAvailableGeometry = m_availableGeometry;
+#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
@@ -369,6 +388,8 @@ void QIOSScreen::updateProperties()
m_physicalSize = physicalGeometry.size() / m_physicalDpi * millimetersPerInch;
}
+#endif // defined(Q_OS_VISIONOS)
+
// 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
@@ -453,16 +474,28 @@ QDpi QIOSScreen::logicalBaseDpi() const
qreal QIOSScreen::devicePixelRatio() const
{
+#if defined(Q_OS_VISIONOS)
+ return 2.0; // Based on what iPad app reports
+#else
return [m_uiScreen scale];
+#endif
}
qreal QIOSScreen::refreshRate() const
{
+#if defined(Q_OS_VISIONOS)
+ return 120.0; // Based on what iPad app reports
+#else
return m_uiScreen.maximumFramesPerSecond;
+#endif
}
Qt::ScreenOrientation QIOSScreen::nativeOrientation() const
{
+#if defined(Q_OS_VISIONOS)
+ // Based on iPad app reporting native bounds 1668x2388
+ return Qt::PortraitOrientation;
+#else
CGRect nativeBounds =
#if defined(Q_OS_IOS)
m_uiScreen.nativeBounds;
@@ -474,11 +507,12 @@ Qt::ScreenOrientation QIOSScreen::nativeOrientation() const
// be on the safe side we compare the width and height of the bounds.
return nativeBounds.size.width >= nativeBounds.size.height ?
Qt::LandscapeOrientation : Qt::PortraitOrientation;
+#endif
}
Qt::ScreenOrientation QIOSScreen::orientation() const
{
-#ifdef Q_OS_TVOS
+#if defined(Q_OS_TVOS) || defined(Q_OS_VISIONOS)
return Qt::PrimaryOrientation;
#else
// Auxiliary screens are always the same orientation as their primary orientation
@@ -540,10 +574,12 @@ QPixmap QIOSScreen::grabWindow(WId window, int x, int y, int width, int height)
return QPixmap::fromImage(qt_mac_toQImage(screenshot.CGImage));
}
+#if !defined(Q_OS_VISIONOS)
UIScreen *QIOSScreen::uiScreen() const
{
return m_uiScreen;
}
+#endif
UIWindow *QIOSScreen::uiWindow() const
{
diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm
index b7377cc5e7..5231a3adde 100644
--- a/src/plugins/platforms/ios/qiostextresponder.mm
+++ b/src/plugins/platforms/ios/qiostextresponder.mm
@@ -401,7 +401,7 @@
if (UIView *accessoryView = static_cast<UIView *>(platformData.value(kImePlatformDataInputAccessoryView).value<void *>()))
self.inputAccessoryView = [[[WrapperView alloc] initWithView:accessoryView] autorelease];
-#ifndef Q_OS_TVOS
+#if !defined(Q_OS_TVOS) && !defined(Q_OS_VISIONOS)
if (platformData.value(kImePlatformDataHideShortcutsBar).toBool()) {
// According to the docs, leadingBarButtonGroups/trailingBarButtonGroups should be set to nil to hide the shortcuts bar.
// However, starting with iOS 10, the API has been surrounded with NS_ASSUME_NONNULL, which contradicts this and causes
diff --git a/src/plugins/platforms/ios/qiostheme.h b/src/plugins/platforms/ios/qiostheme.h
index 0f12ce099c..f0a404a61a 100644
--- a/src/plugins/platforms/ios/qiostheme.h
+++ b/src/plugins/platforms/ios/qiostheme.h
@@ -23,8 +23,10 @@ public:
Qt::ColorScheme colorScheme() const override;
+#if !defined(Q_OS_TVOS) && !defined(Q_OS_VISIONOS)
QPlatformMenuItem* createPlatformMenuItem() const override;
QPlatformMenu* createPlatformMenu() const override;
+#endif
bool usePlatformNativeDialog(DialogType type) const override;
QPlatformDialogHelper *createPlatformDialogHelper(DialogType type) const override;
diff --git a/src/plugins/platforms/ios/qiostheme.mm b/src/plugins/platforms/ios/qiostheme.mm
index 3d6d60f971..251d0434cb 100644
--- a/src/plugins/platforms/ios/qiostheme.mm
+++ b/src/plugins/platforms/ios/qiostheme.mm
@@ -18,12 +18,15 @@
#include <UIKit/UIFont.h>
#include <UIKit/UIInterface.h>
-#ifndef Q_OS_TVOS
+#if !defined(Q_OS_TVOS) && !defined(Q_OS_VISIONOS)
#include "qiosmenu.h"
+#endif
+
+#if !defined(Q_OS_TVOS)
#include "qiosfiledialog.h"
-#include "qiosmessagedialog.h"
#include "qioscolordialog.h"
#include "qiosfontdialog.h"
+#include "qiosmessagedialog.h"
#include "qiosscreen.h"
#endif
@@ -82,23 +85,17 @@ const QPalette *QIOSTheme::palette(QPlatformTheme::Palette type) const
return 0;
}
+#if !defined(Q_OS_TVOS) && !defined(Q_OS_VISIONOS)
QPlatformMenuItem* QIOSTheme::createPlatformMenuItem() const
{
-#ifdef Q_OS_TVOS
- return 0;
-#else
- return new QIOSMenuItem();
-#endif
+ return new QIOSMenuItem;
}
QPlatformMenu* QIOSTheme::createPlatformMenu() const
{
-#ifdef Q_OS_TVOS
- return 0;
-#else
- return new QIOSMenu();
-#endif
+ return new QIOSMenu;
}
+#endif
bool QIOSTheme::usePlatformNativeDialog(QPlatformTheme::DialogType type) const
{
@@ -149,6 +146,13 @@ QVariant QIOSTheme::themeHint(ThemeHint hint) const
Qt::ColorScheme QIOSTheme::colorScheme() const
{
+#if defined(Q_OS_VISIONOS)
+ // On visionOS the concept of light or dark mode does not
+ // apply, as the UI is constantly changing based on what
+ // the lighting conditions are outside the headset, but
+ // the OS reports itself as always being in dark mode.
+ return Qt::ColorScheme::Dark;
+#else
// Set the appearance based on the QUIWindow
// Fallback to the UIScreen if no window is created yet
UIUserInterfaceStyle appearance = UIScreen.mainScreen.traitCollection.userInterfaceStyle;
@@ -163,6 +167,7 @@ Qt::ColorScheme QIOSTheme::colorScheme() const
return appearance == UIUserInterfaceStyleDark
? Qt::ColorScheme::Dark
: Qt::ColorScheme::Light;
+#endif
}
const QFont *QIOSTheme::font(Font type) const
diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm
index 01a8a0d9b2..fa3fef26b6 100644
--- a/src/plugins/platforms/ios/qiosviewcontroller.mm
+++ b/src/plugins/platforms/ios/qiosviewcontroller.mm
@@ -88,6 +88,7 @@
- (void)didAddSubview:(UIView *)subview
{
+#if !defined(Q_OS_VISIONOS)
Q_UNUSED(subview);
QT_PREPEND_NAMESPACE(QIOSScreen) *screen = self.qtViewController.platformScreen;
@@ -103,10 +104,12 @@
uiWindow.screen = screen->uiScreen();
uiWindow.hidden = NO;
}
+#endif
}
- (void)willRemoveSubview:(UIView *)subview
{
+#if !defined(Q_OS_VISIONOS)
Q_UNUSED(subview);
UIWindow *uiWindow = self.window;
@@ -124,6 +127,7 @@
uiWindow.screen = [UIScreen mainScreen];
});
}
+#endif
}
- (void)layoutSubviews
@@ -285,7 +289,7 @@
Q_ASSERT(!qt_apple_isApplicationExtension());
-#ifndef Q_OS_TVOS
+#if !defined(Q_OS_TVOS) && !defined(Q_OS_VISIONOS)
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self selector:@selector(willChangeStatusBarFrame:)
name:UIApplicationWillChangeStatusBarFrameNotification
@@ -307,7 +311,7 @@
- (BOOL)shouldAutorotate
{
-#ifndef Q_OS_TVOS
+#if !defined(Q_OS_TVOS) && !defined(Q_OS_VISIONOS)
return self.platformScreen && self.platformScreen->uiScreen() == [UIScreen mainScreen] && !self.lockedOrientation;
#else
return NO;
@@ -339,6 +343,7 @@
[super didRotateFromInterfaceOrientation:orientation];
}
+#if !defined(Q_OS_VISIONOS)
- (void)willChangeStatusBarFrame:(NSNotification*)notification
{
Q_UNUSED(notification);
@@ -382,6 +387,7 @@
[self.view setNeedsLayout];
}
+#endif
- (void)viewWillLayoutSubviews
{
@@ -402,10 +408,12 @@
if (!self.platformScreen || !self.platformScreen->screen())
return;
+#if !defined(Q_OS_VISIONOS)
// For now we only care about the main screen, as both the statusbar
// visibility and orientation is only appropriate for the main screen.
if (self.platformScreen->uiScreen() != [UIScreen mainScreen])
return;
+#endif
// Prevent recursion caused by updating the status bar appearance (position
// or visibility), which in turn may cause a layout of our subviews, and
@@ -432,7 +440,7 @@
// All decisions are based on the top level window
focusWindow = qt_window_private(focusWindow)->topLevelWindow();
-#ifndef Q_OS_TVOS
+#if !defined(Q_OS_TVOS) && !defined(Q_OS_VISIONOS)
// -------------- Status bar style and visbility ---------------
diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm
index 3631d6be70..398f8c4a6f 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
@@ -42,7 +42,7 @@ QIOSWindow::QIOSWindow(QWindow *window, WId 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);
@@ -304,7 +304,6 @@ void QIOSWindow::requestActivateWindow()
if (blockedByModal())
return;
- Q_ASSERT(m_view.window);
[m_view.window makeKeyWindow];
[m_view becomeFirstResponder];
diff --git a/src/plugins/platforms/ios/quiview.h b/src/plugins/platforms/ios/quiview.h
index 5172585172..7899ec6e0e 100644
--- a/src/plugins/platforms/ios/quiview.h
+++ b/src/plugins/platforms/ios/quiview.h
@@ -34,7 +34,7 @@ QT_END_NAMESPACE
- (QIOSViewController*)qtViewController;
@end
-#ifdef Q_OS_IOS
+#if QT_CONFIG(metal)
@interface QUIMetalView : QUIView
@end
#endif
diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm
index f1103dae9c..58071eed37 100644
--- a/src/plugins/platforms/ios/quiview.mm
+++ b/src/plugins/platforms/ios/quiview.mm
@@ -61,7 +61,7 @@ inline ulong getTimeStamp(UIEvent *event)
+ (void)load
{
-#ifndef Q_OS_TVOS
+#if !defined(Q_OS_TVOS) && !defined(Q_OS_VISIONOS)
if (QOperatingSystemVersion::current() < QOperatingSystemVersion(QOperatingSystemVersion::IOS, 11)) {
// iOS 11 handles this though [UIView safeAreaInsetsDidChange], but there's no signal for
// the corresponding top and bottom layout guides that we use on earlier versions. Note
@@ -197,6 +197,7 @@ inline ulong getTimeStamp(UIEvent *event)
return description;
}
+#if !defined(Q_OS_VISIONOS)
- (void)willMoveToWindow:(UIWindow *)newWindow
{
// UIKIt will normally set the scale factor of a view to match the corresponding
@@ -206,6 +207,7 @@ inline ulong getTimeStamp(UIEvent *event)
// FIXME: Allow the scale factor to be customized through QSurfaceFormat.
}
+#endif
- (void)didAddSubview:(UIView *)subview
{
@@ -700,7 +702,7 @@ inline ulong getTimeStamp(UIEvent *event)
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
-#ifndef Q_OS_TVOS
+#if !defined(Q_OS_TVOS) && !defined(Q_OS_VISIONOS)
// Check first if QIOSMenu should handle the action before continuing up the responder chain
return [QIOSMenu::menuActionTarget() targetForAction:action withSender:sender] != 0;
#else
@@ -713,7 +715,7 @@ inline ulong getTimeStamp(UIEvent *event)
- (id)forwardingTargetForSelector:(SEL)selector
{
Q_UNUSED(selector);
-#ifndef Q_OS_TVOS
+#if !defined(Q_OS_TVOS) && !defined(Q_OS_VISIONOS)
return QIOSMenu::menuActionTarget();
#else
return nil;
@@ -831,7 +833,7 @@ inline ulong getTimeStamp(UIEvent *event)
@end
-#ifdef Q_OS_IOS
+#if QT_CONFIG(metal)
@implementation QUIMetalView
+ (Class)layerClass