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
qiosapplicationdelegate.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
6
7#include "qiosglobal.h"
9#include "qiosservices.h"
11#include "qioswindow.h"
12#include "qiosscreen.h"
13#include "quiwindow.h"
14
15#include <qpa/qplatformintegration.h>
16
17#include <QtCore/QtCore>
18
19#include <QtCore/private/qdarwinsecurityscopedfileengine_p.h>
20
21@interface QIOSWindowSceneDelegate : NSObject<UIWindowSceneDelegate>
22@property (nullable, nonatomic, strong) UIWindow *window;
23@end
24
25@implementation QIOSApplicationDelegate
26
27- (UISceneConfiguration *)application:(UIApplication *)application
28 configurationForConnectingSceneSession:(UISceneSession *)session
29 options:(UISceneConnectionOptions *)options
30{
31 qCDebug(lcQpaWindowScene) << "Configuring scene for" << session << "with options" << options;
32
33 auto *sceneConfig = session.configuration;
34
35 if ([sceneConfig.role hasPrefix:@"CPTemplateApplication"]) {
36 qCDebug(lcQpaWindowScene) << "Not touching CarPlay scene with role" << sceneConfig.role
37 << "and existing delegate class" << sceneConfig.delegateClass;
38 // FIXME: Consider ignoring any scene with an existing sceneClass, delegateClass, or
39 // storyboard. But for visionOS the default delegate is SwiftUI.AppSceneDelegate.
40 } else {
41 sceneConfig.delegateClass = QIOSWindowSceneDelegate.class;
42 }
43
44 return sceneConfig;
45}
46
47@end
48
49@implementation QIOSWindowSceneDelegate
50
51- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions
52{
53 qCDebug(lcQpaWindowScene) << "Connecting" << scene << "to" << session;
54
55 // Handle connection options, even if we return early
56 const auto handleConnectionOptions = qScopeGuard([&]{
57 if (connectionOptions.URLContexts.count > 0)
58 [self scene:scene openURLContexts:connectionOptions.URLContexts];
59 // Handle universal link (https) application cold-launch case
60 for (NSUserActivity *activity in connectionOptions.userActivities)
61 [self scene:scene continueUserActivity:activity];
62 });
63
64#if defined(Q_OS_VISIONOS)
65 // CPImmersiveScene is a UIWindowScene, most likely so it can handle its internal
66 // CPSceneLayerEventWindow and UITextEffectsWindow, but we don't want a QUIWindow
67 // for these scenes, so bail out early.
68 if ([scene.session.role isEqualToString:@"CPSceneSessionRoleImmersiveSpaceApplication"]) {
69 qCDebug(lcQpaWindowScene) << "Skipping UIWindow creation for immersive scene";
70 return;
71 }
72#endif
73
74 if (![scene isKindOfClass:UIWindowScene.class]) {
75 qCWarning(lcQpaWindowScene) << "Unexpectedly encountered non-window scene";
76 return;
77 }
78
79 UIWindowScene *windowScene = static_cast<UIWindowScene*>(scene);
80
81 QUIWindow *window = [[QUIWindow alloc] initWithWindowScene:windowScene];
82 window.rootViewController = [[[QIOSViewController alloc] initWithWindow:window] autorelease];
83
84 self.window = [window autorelease];
85}
86
87- (void)windowScene:(UIWindowScene *)windowScene
88 didUpdateCoordinateSpace:(id<UICoordinateSpace>)previousCoordinateSpace
89 interfaceOrientation:(UIInterfaceOrientation)previousInterfaceOrientation
90 traitCollection:(UITraitCollection *)previousTraitCollection
91{
92 qCDebug(lcQpaWindowScene) << "Scene" << windowScene << "did update properties";
93 if (!self.window)
94 return;
95
96 Q_ASSERT([self.window isKindOfClass:QUIWindow.class]);
97 auto *viewController = static_cast<QIOSViewController*>(self.window.rootViewController);
98 [viewController updatePlatformScreen];
99}
100
101- (void)sceneDidDisconnect:(UIScene *)scene
102{
103 qCDebug(lcQpaWindowScene) << "Disconnecting" << scene;
104 self.window = nil;
105}
106
107- (void)scene:(UIScene *)scene openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts
108{
109 qCDebug(lcQpaWindowScene) << "Handling openURLContexts for scene" << scene;
110
111 QIOSIntegration *iosIntegration = QIOSIntegration::instance();
112 Q_ASSERT(iosIntegration);
113
114 QIOSServices *iosServices = static_cast<QIOSServices *>(iosIntegration->services());
115
116 for (UIOpenURLContext *urlContext in URLContexts) {
117 QUrl url = qt_apple_urlFromPossiblySecurityScopedURL(urlContext.URL);
118 if (url.isLocalFile())
119 QWindowSystemInterface::handleFileOpenEvent(url);
120 else
121 iosServices->handleUrl(url);
122 }
123}
124
125- (void)scene:(UIScene *)scene continueUserActivity:(NSUserActivity *)userActivity
126{
127 qCDebug(lcQpaWindowScene) << "Handling user activity for scene" << scene;
128
129 if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) {
130 QIOSIntegration *iosIntegration = QIOSIntegration::instance();
131 Q_ASSERT(iosIntegration);
132
133 QIOSServices *iosServices = static_cast<QIOSServices *>(iosIntegration->services());
134 iosServices->handleUrl(QUrl::fromNSURL(userActivity.webpageURL));
135 }
136}
137
138@end