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"
20
21#if defined(Q_OS_VISIONOS)
22#include "qiosswiftintegration.h"
23#endif
24
25#include <QtGui/qpointingdevice.h>
26#include <QtGui/private/qguiapplication_p.h>
27#include <QtGui/private/qrhibackingstore_p.h>
28
29#include <qoffscreensurface.h>
30#include <qpa/qplatformoffscreensurface.h>
31
32#include <QtGui/private/qcoretextfontdatabase_p.h>
33#include <QtGui/private/qmacmimeregistry_p.h>
34#include <QtGui/qutimimeconverter.h>
35#include <QDir>
36#include <QOperatingSystemVersion>
37
38#if QT_CONFIG(opengl)
39#include "qioscontext.h"
40#endif
41
42#import <AudioToolbox/AudioServices.h>
43
44#include <QtDebug>
45
47
48using namespace Qt::StringLiterals;
49
50class QCoreTextFontEngine;
51
53{
54 return static_cast<QIOSIntegration *>(QGuiApplicationPrivate::platformIntegration());
55}
56
57QIOSIntegration::QIOSIntegration()
58 : m_fontDatabase(new QCoreTextFontDatabaseEngineFactory<QCoreTextFontEngine>)
59#if QT_CONFIG(clipboard)
60 , m_clipboard(new QIOSClipboard)
61#endif
62 , m_inputContext(0)
63 , m_accessibility(0)
64 , m_optionalPlugins(new QFactoryLoader(QIosOptionalPluginInterface_iid, "/platforms/darwin"_L1))
65{
66 if (Q_UNLIKELY(!qt_apple_isApplicationExtension() && !qt_apple_sharedApplication())) {
67 qFatal("Error: You are creating QApplication before calling UIApplicationMain.\n"
68 "If you are writing a native iOS application, and only want to use Qt for\n"
69 "parts of the application, a good place to create QApplication is from within\n"
70 "'applicationDidFinishLaunching' inside your UIApplication delegate.\n");
71 }
72
73 if (qEnvironmentVariableIsSet("QT_RUNNING_VIA_TEST_RUNNER")) {
74 QDir::temp().mkdir("testrunner");
75 QDir::setCurrent(QDir::temp().filePath("testrunner"));
76 } else {
77 // Set current directory to app bundle folder for the convenience of
78 // examples that load resources relative to the deployment path.
79 // FIXME: This is akward, we should use the home dir or container
80 QDir::setCurrent(QString::fromNSString(NSBundle.mainBundle.bundlePath));
81 }
82}
83
84void QIOSIntegration::initialize()
85{
86 QIOSScreen::initializeScreens();
87
88 // Depends on a primary screen being present
89 m_inputContext = new QIOSInputContext;
90
91 QPointingDevice::Capabilities touchCapabilities = QPointingDevice::Capability::Position | QPointingDevice::Capability::NormalizedPosition;
92#if !defined(Q_OS_VISIONOS)
93 if (UIScreen.mainScreen.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable)
94 touchCapabilities |= QPointingDevice::Capability::Pressure;
95#endif
96 m_touchDevice = new QPointingDevice("touchscreen", 0, QInputDevice::DeviceType::TouchScreen,
97 QPointingDevice::PointerType::Finger, touchCapabilities, 10, 0);
98 QWindowSystemInterface::registerInputDevice(m_touchDevice);
99#if QT_CONFIG(tabletevent)
100 QWindowSystemInterfacePrivate::TabletEvent::setPlatformSynthesizesMouse(false);
101 m_pencilDevice = new QPointingDevice(
102 "Apple Pencil", 0, QInputDevice::DeviceType::Stylus, QPointingDevice::PointerType::Pen,
103 QInputDevice::Capability::Position | QInputDevice::Capability::Pressure
104 | QInputDevice::Capability::XTilt | QInputDevice::Capability::YTilt
105 | QInputDevice::Capability::Hover | QInputDevice::Capability::ZPosition
106 | QInputDevice::Capability::Rotation,
107 1, 0);
108 QWindowSystemInterface::registerInputDevice(m_pencilDevice);
109#endif
110 QMacMimeRegistry::initializeMimeTypes();
111
112 qsizetype size = QList<QPluginParsedMetaData>(m_optionalPlugins->metaData()).size();
113 for (qsizetype i = 0; i < size; ++i)
114 qobject_cast<QIosOptionalPluginInterface *>(m_optionalPlugins->instance(i))->initPlugin();
115}
116
117QIOSIntegration::~QIOSIntegration()
118{
119 delete m_fontDatabase;
120 m_fontDatabase = 0;
121
122#if QT_CONFIG(clipboard)
123 delete m_clipboard;
124 m_clipboard = 0;
125#endif
126
127 QMacMimeRegistry::destroyMimeTypes();
128
129 delete m_inputContext;
130 m_inputContext = 0;
131
132 foreach (QScreen *screen, QGuiApplication::screens())
133 QWindowSystemInterface::handleScreenRemoved(screen->handle());
134
135 delete m_platformServices;
136 m_platformServices = 0;
137
138 delete m_accessibility;
139 m_accessibility = 0;
140
141 delete m_optionalPlugins;
142 m_optionalPlugins = 0;
143}
144
145bool QIOSIntegration::hasCapability(Capability cap) const
146{
147 switch (cap) {
148#if QT_CONFIG(opengl)
149 case BufferQueueingOpenGL:
150 return true;
151 case OpenGL:
152 case ThreadedOpenGL:
153 return true;
154#endif
155 case ThreadedPixmaps:
156 return true;
157 case MultipleWindows:
158 return true;
159 case WindowManagement:
160 return false;
161 case ApplicationState:
162 return true;
163 case ForeignWindows:
164 return true;
165 default:
166 return QPlatformIntegration::hasCapability(cap);
167 }
168}
169
170QPlatformWindow *QIOSIntegration::createPlatformWindow(QWindow *window) const
171{
172 return new QIOSWindow(window);
173}
174
175QPlatformWindow *QIOSIntegration::createForeignWindow(QWindow *window, WId nativeHandle) const
176{
177 return new QIOSWindow(window, nativeHandle);
178}
179
180QPlatformBackingStore *QIOSIntegration::createPlatformBackingStore(QWindow *window) const
181{
182 return new QRhiBackingStore(window);
183}
184
185#if QT_CONFIG(opengl)
186// Used when the QWindow's surface type is set by the client to QSurface::OpenGLSurface
187QPlatformOpenGLContext *QIOSIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
188{
189 return new QIOSContext(context);
190}
191#endif
192
193class QIOSOffscreenSurface : public QPlatformOffscreenSurface
194{
195public:
196 QIOSOffscreenSurface(QOffscreenSurface *offscreenSurface) : QPlatformOffscreenSurface(offscreenSurface) {}
197
198 QSurfaceFormat format() const override
199 {
200 Q_ASSERT(offscreenSurface());
201 return offscreenSurface()->requestedFormat();
202 }
203 bool isValid() const override { return true; }
204};
205
206QPlatformOffscreenSurface *QIOSIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const
207{
208 return new QIOSOffscreenSurface(surface);
209}
210
212{
213 return QIOSEventDispatcher::create();
214}
215
217{
218 return m_fontDatabase;
219}
220
221#if QT_CONFIG(clipboard)
222QPlatformClipboard *QIOSIntegration::clipboard() const
223{
224 return m_clipboard;
225}
226#endif
227
229{
230 return m_inputContext;
231}
232
234{
235 if (!m_platformServices)
236 m_platformServices = new QIOSServices;
237
238 return m_platformServices;
239}
240
241QVariant QIOSIntegration::styleHint(StyleHint hint) const
242{
243 switch (hint) {
244 case StartDragTime:
245 return 300;
246 case PasswordMaskDelay:
247 // this number is based on timing the native delay
248 // since there is no API to get it
249 return 2000;
250 case ShowIsMaximized:
251 return true;
252 case SetFocusOnTouchRelease:
253 return true;
254 default:
255 return QPlatformIntegration::styleHint(hint);
256 }
257}
258
260{
261 return QStringList(QLatin1StringView(QIOSTheme::name));
262}
263
265{
266 if (name == QLatin1StringView(QIOSTheme::name))
267 return new QIOSTheme;
268
269 return QPlatformIntegration::createPlatformTheme(name);
270}
271
273{
274 return m_touchDevice;
275}
276
277#if QT_CONFIG(tabletevent)
278QPointingDevice *QIOSIntegration::pencilDevice()
279{
280 return m_pencilDevice;
281}
282#endif
283
284#if QT_CONFIG(accessibility)
285QPlatformAccessibility *QIOSIntegration::accessibility() const
286{
287 if (!m_accessibility)
288 m_accessibility = new QIOSPlatformAccessibility;
289 return m_accessibility;
290}
291#endif
292
294{
295 return const_cast<QIOSIntegration *>(this);
296}
297
299{
300#if !TARGET_IPHONE_SIMULATOR
301 AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);
302#endif
303}
304
306{
307 UIApplication.sharedApplication.applicationIconBadgeNumber = number;
308}
309
310// ---------------------------------------------------------
311
312#if defined(Q_OS_VISIONOS)
313void QIOSIntegration::openImmersiveSpace()
314{
315 [ImmersiveSpaceManager openImmersiveSpace];
316}
317
318void QIOSIntegration::dismissImmersiveSpace()
319{
320 [ImmersiveSpaceManager dismissImmersiveSpace];
321}
322
323void QIOSIntegration::setImmersiveSpaceCompositorLayer(CompositorLayer *layer)
324{
325 m_immersiveSpaceCompositorLayer = layer;
326}
327
328void QIOSIntegration::configureCompositorLayer(cp_layer_renderer_capabilities_t capabilities,
329 cp_layer_renderer_configuration_t configuration)
330{
331 if (m_immersiveSpaceCompositorLayer)
332 m_immersiveSpaceCompositorLayer->configure(capabilities, configuration);
333}
334
335void QIOSIntegration::renderCompositorLayer(cp_layer_renderer_t renderer)
336{
337 if (m_immersiveSpaceCompositorLayer)
338 m_immersiveSpaceCompositorLayer->render(renderer);
339}
340
341void QIOSIntegration::handleSpatialEvents(const char *jsonString)
342{
343 if (m_immersiveSpaceCompositorLayer) {
344 QJsonParseError error;
345 QJsonDocument doc = QJsonDocument::fromJson(QByteArray(jsonString), &error);
346 if (error.error != QJsonParseError::NoError) {
347 qWarning() << "Error parsing JSON: " << error.errorString();
348 return;
349 }
350 m_immersiveSpaceCompositorLayer->handleSpatialEvents(doc.object());
351 }
352}
353
354#endif
355
356// ---------------------------------------------------------
357
358void *QIOSIntegration::nativeResourceForWindow(const QByteArray &resource, QWindow *window)
359{
360 if (!window || !window->handle())
361 return 0;
362
363 QByteArray lowerCaseResource = resource.toLower();
364
365 QIOSWindow *platformWindow = static_cast<QIOSWindow *>(window->handle());
366
367 if (lowerCaseResource == "uiview")
368 return reinterpret_cast<void *>(platformWindow->winId());
369
370 return 0;
371}
372
373// ---------------------------------------------------------
374
375QT_END_NAMESPACE
376
377#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