Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
platform_view_ios.mm
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#import "flutter/shell/platform/darwin/ios/platform_view_ios.h"
6#include <memory>
7
8#include <utility>
9
10#include "flutter/common/task_runners.h"
11#include "flutter/fml/synchronization/waitable_event.h"
12#include "flutter/fml/trace_event.h"
13#include "flutter/shell/common/shell_io_manager.h"
14#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h"
15#import "flutter/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.h"
16
17namespace flutter {
18
19PlatformViewIOS::AccessibilityBridgeManager::AccessibilityBridgeManager(
20 const std::function<void(bool)>& set_semantics_enabled)
21 : AccessibilityBridgeManager(set_semantics_enabled, nullptr) {}
22
23PlatformViewIOS::AccessibilityBridgeManager::AccessibilityBridgeManager(
24 const std::function<void(bool)>& set_semantics_enabled,
25 AccessibilityBridge* bridge)
26 : accessibility_bridge_(bridge), set_semantics_enabled_(set_semantics_enabled) {
27 if (bridge) {
28 set_semantics_enabled_(true);
29 }
30}
31
32void PlatformViewIOS::AccessibilityBridgeManager::Set(std::unique_ptr<AccessibilityBridge> bridge) {
33 accessibility_bridge_ = std::move(bridge);
34 set_semantics_enabled_(true);
35}
36
37void PlatformViewIOS::AccessibilityBridgeManager::Clear() {
38 set_semantics_enabled_(false);
39 accessibility_bridge_.reset();
40}
41
42PlatformViewIOS::PlatformViewIOS(
43 PlatformView::Delegate& delegate,
44 const std::shared_ptr<IOSContext>& context,
45 const std::shared_ptr<FlutterPlatformViewsController>& platform_views_controller,
46 const flutter::TaskRunners& task_runners)
47 : PlatformView(delegate, task_runners),
48 ios_context_(context),
49 platform_views_controller_(platform_views_controller),
50 accessibility_bridge_([this](bool enabled) { PlatformView::SetSemanticsEnabled(enabled); }),
51 platform_message_handler_(
52 new PlatformMessageHandlerIos(task_runners.GetPlatformTaskRunner())) {}
53
55 PlatformView::Delegate& delegate,
56 IOSRenderingAPI rendering_api,
57 const std::shared_ptr<FlutterPlatformViewsController>& platform_views_controller,
58 const flutter::TaskRunners& task_runners,
59 const std::shared_ptr<fml::ConcurrentTaskRunner>& worker_task_runner,
60 const std::shared_ptr<const fml::SyncSwitch>& is_gpu_disabled_sync_switch)
62 delegate,
64 rendering_api,
65 delegate.OnPlatformViewGetSettings().enable_impeller ? IOSRenderingBackend::kImpeller
67 static_cast<MsaaSampleCount>(delegate.OnPlatformViewGetSettings().msaa_samples),
68 is_gpu_disabled_sync_switch),
69 platform_views_controller,
70 task_runners) {}
71
73
74// |PlatformView|
75void PlatformViewIOS::HandlePlatformMessage(std::unique_ptr<flutter::PlatformMessage> message) {
76 platform_message_handler_->HandlePlatformMessage(std::move(message));
77}
78
82
84 const fml::WeakNSObject<FlutterViewController>& owner_controller) {
86 std::lock_guard<std::mutex> guard(ios_surface_mutex_);
87 if (ios_surface_ || !owner_controller) {
89 ios_surface_.reset();
90 accessibility_bridge_.Clear();
91 }
92 owner_controller_ = owner_controller;
93
94 // Add an observer that will clear out the owner_controller_ ivar and
95 // the accessibility_bridge_ in case the view controller is deleted.
96 dealloc_view_controller_observer_.reset(
97 [[[NSNotificationCenter defaultCenter] addObserverForName:FlutterViewControllerWillDealloc
98 object:owner_controller_.get()
99 queue:[NSOperationQueue mainQueue]
100 usingBlock:^(NSNotification* note) {
101 // Implicit copy of 'this' is fine.
102 accessibility_bridge_.Clear();
103 owner_controller_.reset();
104 }] retain]);
105
106 if (owner_controller_ && [owner_controller_.get() isViewLoaded]) {
107 this->attachView();
108 }
109 // Do not call `NotifyCreated()` here - let FlutterViewController take care
110 // of that when its Viewport is sized. If `NotifyCreated()` is called here,
111 // it can occasionally get invoked before the viewport is sized resulting in
112 // a framebuffer that will not be able to completely attach.
113}
114
116 FML_DCHECK(owner_controller_);
117 FML_DCHECK(owner_controller_.get().isViewLoaded)
118 << "FlutterViewController's view should be loaded "
119 "before attaching to PlatformViewIOS.";
120 auto flutter_view = static_cast<FlutterView*>(owner_controller_.get().view);
121 auto ca_layer = fml::scoped_nsobject<CALayer>{[[flutter_view layer] retain]};
122 ios_surface_ = IOSSurface::Create(ios_context_, ca_layer);
123 FML_DCHECK(ios_surface_ != nullptr);
124
125 if (accessibility_bridge_) {
126 accessibility_bridge_.Set(std::make_unique<AccessibilityBridge>(
127 owner_controller_.get(), this, [owner_controller_.get() platformViewsController]));
128 }
129}
130
132 return [](DefaultPointerDataDispatcher::Delegate& delegate) {
133 return std::make_unique<SmoothPointerDataDispatcher>(delegate);
134 };
135}
136
138 NSObject<FlutterTexture>* texture) {
139 RegisterTexture(ios_context_->CreateExternalTexture(
140 texture_id, fml::scoped_nsobject<NSObject<FlutterTexture>>{[texture retain]}));
141}
142
143// |PlatformView|
144std::unique_ptr<Surface> PlatformViewIOS::CreateRenderingSurface() {
146 std::lock_guard<std::mutex> guard(ios_surface_mutex_);
147 if (!ios_surface_) {
148 FML_DLOG(INFO) << "Could not CreateRenderingSurface, this PlatformViewIOS "
149 "has no ViewController.";
150 return nullptr;
151 }
152 return ios_surface_->CreateGPUSurface(ios_context_->GetMainContext().get());
153}
154
155// |PlatformView|
156std::shared_ptr<ExternalViewEmbedder> PlatformViewIOS::CreateExternalViewEmbedder() {
157 return std::make_shared<IOSExternalViewEmbedder>(platform_views_controller_, ios_context_);
158}
159
160// |PlatformView|
162 return ios_context_->CreateResourceContext();
163}
164
165// |PlatformView|
166std::shared_ptr<impeller::Context> PlatformViewIOS::GetImpellerContext() const {
167 return ios_context_->GetImpellerContext();
168}
169
170// |PlatformView|
172 if (!owner_controller_) {
173 FML_LOG(WARNING) << "Could not set semantics to enabled, this "
174 "PlatformViewIOS has no ViewController.";
175 return;
176 }
177 if (enabled && !accessibility_bridge_) {
178 accessibility_bridge_.Set(std::make_unique<AccessibilityBridge>(
179 owner_controller_.get(), this, [owner_controller_.get() platformViewsController]));
180 } else if (!enabled && accessibility_bridge_) {
181 accessibility_bridge_.Clear();
182 } else {
184 }
185}
186
187// |shell:PlatformView|
191
192// |PlatformView|
195 FML_DCHECK(owner_controller_);
196 if (accessibility_bridge_) {
197 accessibility_bridge_.get()->UpdateSemantics(std::move(update), actions);
198 [[NSNotificationCenter defaultCenter] postNotificationName:FlutterSemanticsUpdateNotification
199 object:owner_controller_.get()];
200 }
201}
202
203// |PlatformView|
204std::unique_ptr<VsyncWaiter> PlatformViewIOS::CreateVSyncWaiter() {
205 return std::make_unique<VsyncWaiterIOS>(task_runners_);
206}
207
209 if (accessibility_bridge_) {
210 accessibility_bridge_.get()->clearState();
211 }
212 if (!owner_controller_) {
213 return;
214 }
215 [owner_controller_.get() platformViewsController]->Reset();
216 [[owner_controller_.get() restorationPlugin] reset];
217}
218
219std::unique_ptr<std::vector<std::string>> PlatformViewIOS::ComputePlatformResolvedLocales(
220 const std::vector<std::string>& supported_locale_data) {
221 size_t localeDataLength = 3;
222 NSMutableArray<NSString*>* supported_locale_identifiers =
223 [NSMutableArray arrayWithCapacity:supported_locale_data.size() / localeDataLength];
224 for (size_t i = 0; i < supported_locale_data.size(); i += localeDataLength) {
225 NSDictionary<NSString*, NSString*>* dict = @{
226 NSLocaleLanguageCode : [NSString stringWithUTF8String:supported_locale_data[i].c_str()]
227 ?: @"",
228 NSLocaleCountryCode : [NSString stringWithUTF8String:supported_locale_data[i + 1].c_str()]
229 ?: @"",
230 NSLocaleScriptCode : [NSString stringWithUTF8String:supported_locale_data[i + 2].c_str()]
231 ?: @""
232 };
233 [supported_locale_identifiers addObject:[NSLocale localeIdentifierFromComponents:dict]];
234 }
235 NSArray<NSString*>* result =
236 [NSBundle preferredLocalizationsFromArray:supported_locale_identifiers];
237
238 // Output format should be either empty or 3 strings for language, country, and script.
239 std::unique_ptr<std::vector<std::string>> out = std::make_unique<std::vector<std::string>>();
240
241 if (result != nullptr && [result count] > 0) {
242 NSLocale* locale = [NSLocale localeWithLocaleIdentifier:[result firstObject]];
243 NSString* languageCode = [locale languageCode];
244 out->emplace_back(languageCode == nullptr ? "" : languageCode.UTF8String);
245 NSString* countryCode = [locale countryCode];
246 out->emplace_back(countryCode == nullptr ? "" : countryCode.UTF8String);
247 NSString* scriptCode = [locale scriptCode];
248 out->emplace_back(scriptCode == nullptr ? "" : scriptCode.UTF8String);
249 }
250 return out;
251}
252
253PlatformViewIOS::ScopedObserver::ScopedObserver() {}
254
255PlatformViewIOS::ScopedObserver::~ScopedObserver() {
256 if (observer_) {
257 [[NSNotificationCenter defaultCenter] removeObserver:observer_];
258 [observer_ release];
259 }
260}
261
262void PlatformViewIOS::ScopedObserver::reset(id<NSObject> observer) {
263 if (observer != observer_) {
264 if (observer_) {
265 [[NSNotificationCenter defaultCenter] removeObserver:observer_];
266 [observer_ release];
267 }
268 observer_ = observer;
269 }
270}
271
272} // namespace flutter
m reset()
int count
static sk_sp< Effect > Create()
Manages the lifetime of the on-screen and off-screen rendering contexts on iOS. On-screen contexts ar...
Definition ios_context.h:40
static std::unique_ptr< IOSSurface > Create(std::shared_ptr< IOSContext > context, const fml::scoped_nsobject< CALayer > &layer)
std::unique_ptr< Surface > CreateRenderingSurface() override
PointerDataDispatcherMaker GetDispatcherMaker() override
Returns a platform-specific PointerDataDispatcherMaker so the Engine can construct the PointerDataPac...
sk_sp< GrDirectContext > CreateResourceContext() const override
Used by the shell to obtain a Skia GPU context that is capable of operating on the IO thread....
std::shared_ptr< impeller::Context > GetImpellerContext() const override
void SetAccessibilityFeatures(int32_t flags) override
Used by the embedder to specify the features to enable in the accessibility tree generated by the iso...
void SetOwnerViewController(const fml::WeakNSObject< FlutterViewController > &owner_controller)
std::unique_ptr< VsyncWaiter > CreateVSyncWaiter() override
Invoked by the shell to obtain a platform specific vsync waiter. It is optional for platforms to over...
PlatformViewIOS(PlatformView::Delegate &delegate, const std::shared_ptr< IOSContext > &context, const std::shared_ptr< FlutterPlatformViewsController > &platform_views_controller, const flutter::TaskRunners &task_runners)
std::shared_ptr< ExternalViewEmbedder > CreateExternalViewEmbedder() override
void SetSemanticsEnabled(bool enabled) override
Used by embedder to notify the running isolate hosted by the engine on the UI thread that the accessi...
void HandlePlatformMessage(std::unique_ptr< flutter::PlatformMessage > message) override
Overridden by embedders to perform actions in response to platform messages sent from the framework t...
fml::WeakNSObject< FlutterViewController > GetOwnerViewController() const
void OnPreEngineRestart() const override
Gives embedders a chance to react to a "cold restart" of the running isolate. The default implementat...
void RegisterExternalTexture(int64_t id, NSObject< FlutterTexture > *texture)
void UpdateSemantics(flutter::SemanticsNodeUpdates update, flutter::CustomAccessibilityActionUpdates actions) override
Used by the framework to tell the embedder to apply the specified semantics node updates....
std::unique_ptr< std::vector< std::string > > ComputePlatformResolvedLocales(const std::vector< std::string > &supported_locale_data) override
Directly invokes platform-specific APIs to compute the locale the platform would have natively resolv...
Used to forward events from the platform view to interested subsystems. This forwarding is done by th...
Platform views are created by the shell on the platform task runner. Unless explicitly specified,...
virtual void SetAccessibilityFeatures(int32_t flags)
Used by the embedder to specify the features to enable in the accessibility tree generated by the iso...
virtual void NotifyDestroyed()
Used by embedders to notify the shell that the platform view has been destroyed. This notification us...
void RegisterTexture(std::shared_ptr< flutter::Texture > texture)
Used by the embedder to specify a texture that it wants the rasterizer to composite within the Flutte...
const TaskRunners task_runners_
virtual void SetSemanticsEnabled(bool enabled)
Used by embedder to notify the running isolate hosted by the engine on the UI thread that the accessi...
The interface for Engine to implement.
fml::RefPtr< fml::TaskRunner > GetRasterTaskRunner() const
fml::RefPtr< fml::TaskRunner > GetPlatformTaskRunner() const
virtual bool RunsTasksOnCurrentThread()
VkQueue queue
Definition main.cc:55
FlutterSemanticsFlag flags
GAsyncResult * result
#define FML_DLOG(severity)
Definition logging.h:102
#define FML_LOG(severity)
Definition logging.h:82
#define FML_DCHECK(condition)
Definition logging.h:103
FLUTTER_DARWIN_EXPORT NSNotificationName const FlutterSemanticsUpdateNotification
NSNotificationName const FlutterViewControllerWillDealloc
Win32Message message
FlTexture * texture
MsaaSampleCount
std::unordered_map< int32_t, SemanticsNode > SemanticsNodeUpdates
std::unordered_map< int32_t, CustomAccessibilityAction > CustomAccessibilityActionUpdates
std::function< std::unique_ptr< PointerDataDispatcher >(PointerDataDispatcher::Delegate &)> PointerDataDispatcherMaker
Signature for constructing PointerDataDispatcher.
int64_t texture_id