Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qiosintegration.mm
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses
6
9#include "qiosglobal.h"
10#include "qioswindow.h"
11#include "qiosscreen.h"
13#if QT_CONFIG(clipboard)
14#include "qiosclipboard.h"
15#endif
17#include "qiostheme.h"
18#include "qiosservices.h"
21
22#if defined(Q_OS_VISIONOS)
23#include "qiosswiftintegration.h"
24#endif
25
26#include <QtGui/qpointingdevice.h>
27#include <QtGui/private/qguiapplication_p.h>
28#include <QtGui/private/qrhibackingstore_p.h>
29
30#include <qoffscreensurface.h>
31#include <qpa/qplatformoffscreensurface.h>
32
33#include <QtGui/private/qcoretextfontdatabase_p.h>
34#include <QtGui/private/qmacmimeregistry_p.h>
35#include <QtGui/qutimimeconverter.h>
36#include <QDir>
37#include <QOperatingSystemVersion>
38
39#if QT_CONFIG(opengl)
40#include "qioscontext.h"
41#endif
42
43#import <AudioToolbox/AudioServices.h>
44
45#include <QtDebug>
46
48
49using namespace Qt::StringLiterals;
50
51class QCoreTextFontEngine;
52
54{
55 return static_cast<QIOSIntegration *>(QGuiApplicationPrivate::platformIntegration());
56}
57
58QIOSIntegration::QIOSIntegration()
59 : m_fontDatabase(new QCoreTextFontDatabaseEngineFactory<QCoreTextFontEngine>)
60#if QT_CONFIG(clipboard)
61 , m_clipboard(new QIOSClipboard)
62#endif
63 , m_inputContext(0)
64 , m_accessibility(0)
65 , m_optionalPlugins(new QFactoryLoader(QIosOptionalPluginInterface_iid, "/platforms/darwin"_L1))
66{
67 if (Q_UNLIKELY(!qt_apple_isApplicationExtension() && !qt_apple_sharedApplication())) {
68 qFatal("Error: You are creating QApplication before calling UIApplicationMain.\n"
69 "If you are writing a native iOS application, and only want to use Qt for\n"
70 "parts of the application, a good place to create QApplication is from within\n"
71 "'applicationDidFinishLaunching' inside your UIApplication delegate.\n");
72 }
73}
74
75void QIOSIntegration::initialize()
76{
77 QIOSScreen::initializeScreens();
78
79 // Depends on a primary screen being present
80 m_inputContext = new QIOSInputContext;
81
82 QPointingDevice::Capabilities touchCapabilities = QPointingDevice::Capability::Position;
83#if !defined(Q_OS_VISIONOS)
84 if (UIScreen.mainScreen.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable)
85 touchCapabilities |= QPointingDevice::Capability::Pressure;
86#endif
87 m_touchDevice = new QPointingDevice("touchscreen", 0, QInputDevice::DeviceType::TouchScreen,
88 QPointingDevice::PointerType::Finger, touchCapabilities, 10, 0);
89 QWindowSystemInterface::registerInputDevice(m_touchDevice);
90#if QT_CONFIG(tabletevent)
91 QWindowSystemInterfacePrivate::TabletEvent::setPlatformSynthesizesMouse(false);
92 m_pencilDevice = new QPointingDevice(
93 "Apple Pencil", 0, QInputDevice::DeviceType::Stylus, QPointingDevice::PointerType::Pen,
94 QInputDevice::Capability::Position | QInputDevice::Capability::Pressure
95 | QInputDevice::Capability::XTilt | QInputDevice::Capability::YTilt
96 | QInputDevice::Capability::Hover | QInputDevice::Capability::ZPosition
97 | QInputDevice::Capability::Rotation,
98 1, 0);
99 QWindowSystemInterface::registerInputDevice(m_pencilDevice);
100#endif
101 QMacMimeRegistry::initializeMimeTypes();
102
103 qsizetype size = QList<QPluginParsedMetaData>(m_optionalPlugins->metaData()).size();
104 for (qsizetype i = 0; i < size; ++i)
105 qobject_cast<QIosOptionalPluginInterface *>(m_optionalPlugins->instance(i))->initPlugin();
106
107 // On visionOS the Swift entry point is used, which sets up the application
108 // delegate itself, so we don't want to install the QIOSApplicationDelegate
109#if !defined(Q_OS_VISIONOS)
110 if (QIOSEventDispatcher::isQtApplication()) {
111 qCDebug(lcQpaWindowScene) << "Replacing application delegate"
112 << UIApplication.sharedApplication.delegate << "with QIOSApplicationDelegate";
113 UIApplication.sharedApplication.delegate = [QIOSApplicationDelegate new];
114 }
115#endif
116}
117
118QIOSIntegration::~QIOSIntegration()
119{
120 delete m_fontDatabase;
121 m_fontDatabase = 0;
122
123#if QT_CONFIG(clipboard)
124 delete m_clipboard;
125 m_clipboard = 0;
126#endif
127
128 QMacMimeRegistry::destroyMimeTypes();
129
130 delete m_inputContext;
131 m_inputContext = 0;
132
133 foreach (QScreen *screen, QGuiApplication::screens())
134 QWindowSystemInterface::handleScreenRemoved(screen->handle());
135
136 delete m_platformServices;
137 m_platformServices = 0;
138
139 delete m_accessibility;
140 m_accessibility = 0;
141
142 delete m_optionalPlugins;
143 m_optionalPlugins = 0;
144}
145
146bool QIOSIntegration::hasCapability(Capability cap) const
147{
148 switch (cap) {
149#if QT_CONFIG(opengl)
150 case BufferQueueingOpenGL:
151 return true;
152 case OpenGL:
153 case ThreadedOpenGL:
154 return true;
155#endif
156 case ThreadedPixmaps:
157 return true;
158 case MultipleWindows:
159 return true;
160 case WindowManagement:
161 return false;
162 case ApplicationState:
163 return true;
164 case ForeignWindows:
165 return true;
166 case ChildWindows:
167 return true;
168 default:
169 return QPlatformIntegration::hasCapability(cap);
170 }
171}
172
173QPlatformWindow *QIOSIntegration::createPlatformWindow(QWindow *window) const
174{
175 return new QIOSWindow(window);
176}
177
178QPlatformWindow *QIOSIntegration::createForeignWindow(QWindow *window, WId nativeHandle) const
179{
180 return new QIOSWindow(window, nativeHandle);
181}
182
183QPlatformBackingStore *QIOSIntegration::createPlatformBackingStore(QWindow *window) const
184{
185 return new QRhiBackingStore(window);
186}
187
188#if QT_CONFIG(opengl)
189// Used when the QWindow's surface type is set by the client to QSurface::OpenGLSurface
190QPlatformOpenGLContext *QIOSIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
191{
192 return new QIOSContext(context);
193}
194#endif
195
196class QIOSOffscreenSurface : public QPlatformOffscreenSurface
197{
198public:
199 QIOSOffscreenSurface(QOffscreenSurface *offscreenSurface) : QPlatformOffscreenSurface(offscreenSurface) {}
200
201 QSurfaceFormat format() const override
202 {
203 Q_ASSERT(offscreenSurface());
204 return offscreenSurface()->requestedFormat();
205 }
206 bool isValid() const override { return true; }
207};
208
209QPlatformOffscreenSurface *QIOSIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const
210{
211 return new QIOSOffscreenSurface(surface);
212}
213
215{
216 return QIOSEventDispatcher::create();
217}
218
220{
221 return m_fontDatabase;
222}
223
224#if QT_CONFIG(clipboard)
225QPlatformClipboard *QIOSIntegration::clipboard() const
226{
227 return m_clipboard;
228}
229#endif
230
232{
233 return m_inputContext;
234}
235
237{
238 if (!m_platformServices)
239 m_platformServices = new QIOSServices;
240
241 return m_platformServices;
242}
243
244QVariant QIOSIntegration::styleHint(StyleHint hint) const
245{
246 switch (hint) {
247 case StartDragTime:
248 return 300;
249 case PasswordMaskDelay:
250 // this number is based on timing the native delay
251 // since there is no API to get it
252 return 2000;
253 case ShowIsMaximized:
254 return true;
255 case SetFocusOnTouchRelease:
256 return true;
257 default:
258 return QPlatformIntegration::styleHint(hint);
259 }
260}
261
263{
264 return QStringList(QLatin1StringView(QIOSTheme::name));
265}
266
268{
269 if (name == QLatin1StringView(QIOSTheme::name))
270 return new QIOSTheme;
271
272 return QPlatformIntegration::createPlatformTheme(name);
273}
274
276{
277 return m_touchDevice;
278}
279
280#if QT_CONFIG(tabletevent)
281QPointingDevice *QIOSIntegration::pencilDevice()
282{
283 return m_pencilDevice;
284}
285#endif
286
287#if QT_CONFIG(accessibility)
288QPlatformAccessibility *QIOSIntegration::accessibility() const
289{
290 if (!m_accessibility)
291 m_accessibility = new QIOSPlatformAccessibility;
292 return m_accessibility;
293}
294#endif
295
297{
298 return const_cast<QIOSIntegration *>(this);
299}
300
302{
303#if !TARGET_IPHONE_SIMULATOR
304 AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);
305#endif
306}
307
309{
310 UIApplication.sharedApplication.applicationIconBadgeNumber = number;
311}
312
313// ---------------------------------------------------------
314
315#if defined(Q_OS_VISIONOS)
316void QIOSIntegration::openImmersiveSpace()
317{
318 [ImmersiveSpaceManager openImmersiveSpace];
319}
320
321void QIOSIntegration::dismissImmersiveSpace()
322{
323 [ImmersiveSpaceManager dismissImmersiveSpace];
324}
325
326void QIOSIntegration::setImmersiveSpaceCompositorLayer(CompositorLayer *layer)
327{
328 m_immersiveSpaceCompositorLayer = layer;
329}
330
331void QIOSIntegration::configureCompositorLayer(cp_layer_renderer_capabilities_t capabilities,
332 cp_layer_renderer_configuration_t configuration)
333{
334 if (m_immersiveSpaceCompositorLayer)
335 m_immersiveSpaceCompositorLayer->configure(capabilities, configuration);
336}
337
338void QIOSIntegration::renderCompositorLayer(cp_layer_renderer_t renderer)
339{
340 if (m_immersiveSpaceCompositorLayer)
341 m_immersiveSpaceCompositorLayer->render(renderer);
342}
343
344void QIOSIntegration::handleSpatialEvents(const char *jsonString)
345{
346 if (m_immersiveSpaceCompositorLayer) {
347 QJsonParseError error;
348 QJsonDocument doc = QJsonDocument::fromJson(QByteArray(jsonString), &error);
349 if (error.error != QJsonParseError::NoError) {
350 qWarning() << "Error parsing JSON: " << error.errorString();
351 return;
352 }
353 m_immersiveSpaceCompositorLayer->handleSpatialEvents(doc.object());
354 }
355}
356
357#endif
358
359// ---------------------------------------------------------
360
361void *QIOSIntegration::nativeResourceForWindow(const QByteArray &resource, QWindow *window)
362{
363 if (!window || !window->handle())
364 return 0;
365
366 QByteArray lowerCaseResource = resource.toLower();
367
368 QIOSWindow *platformWindow = static_cast<QIOSWindow *>(window->handle());
369
370 if (lowerCaseResource == "uiview")
371 return reinterpret_cast<void *>(platformWindow->winId());
372
373 return 0;
374}
375
376// ---------------------------------------------------------
377
378QT_END_NAMESPACE
379
380#include "moc_qiosintegration.cpp"
QVariant styleHint(StyleHint hint) const override
QPlatformTheme * createPlatformTheme(const QString &name) const override
void beep() const override
static QIOSIntegration * instance()
void setApplicationBadge(qint64 number) override
QPointingDevice * touchDevice()
QStringList themeNames() const override
QPlatformNativeInterface * nativeInterface() const override
QAbstractEventDispatcher * createEventDispatcher() const override
Factory function for the GUI event dispatcher.
QPlatformServices * services() const override
QPlatformInputContext * inputContext() const override
Returns the platforms input context.
QPlatformFontDatabase * fontDatabase() const override
Accessor for the platform integration's fontdatabase.
static const char * name
Definition qiostheme.h:44
Combined button and popup list for selecting options.
#define QIosOptionalPluginInterface_iid