Flutter iOS Embedder
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 
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"
16 
18 
19 namespace flutter {
20 
21 PlatformViewIOS::AccessibilityBridgeManager::AccessibilityBridgeManager(
22  const std::function<void(bool)>& set_semantics_enabled)
23  : AccessibilityBridgeManager(set_semantics_enabled, nullptr) {}
24 
25 PlatformViewIOS::AccessibilityBridgeManager::AccessibilityBridgeManager(
26  const std::function<void(bool)>& set_semantics_enabled,
27  AccessibilityBridge* bridge)
28  : accessibility_bridge_(bridge), set_semantics_enabled_(set_semantics_enabled) {
29  if (bridge) {
30  set_semantics_enabled_(true);
31  }
32 }
33 
34 void PlatformViewIOS::AccessibilityBridgeManager::Set(std::unique_ptr<AccessibilityBridge> bridge) {
35  accessibility_bridge_ = std::move(bridge);
36  set_semantics_enabled_(true);
37 }
38 
39 void PlatformViewIOS::AccessibilityBridgeManager::Clear() {
40  set_semantics_enabled_(false);
41  accessibility_bridge_.reset();
42 }
43 
44 PlatformViewIOS::PlatformViewIOS(PlatformView::Delegate& delegate,
45  const std::shared_ptr<IOSContext>& context,
46  __weak FlutterPlatformViewsController* platform_views_controller,
47  const flutter::TaskRunners& task_runners)
48  : PlatformView(delegate, task_runners),
49  ios_context_(context),
50  platform_views_controller_(platform_views_controller),
51  accessibility_bridge_([this](bool enabled) { PlatformView::SetSemanticsEnabled(enabled); }),
52  platform_message_handler_(
53  new PlatformMessageHandlerIos(task_runners.GetPlatformTaskRunner())) {}
54 
56  PlatformView::Delegate& delegate,
57  IOSRenderingAPI rendering_api,
58  __weak FlutterPlatformViewsController* platform_views_controller,
59  const flutter::TaskRunners& task_runners,
60  const std::shared_ptr<fml::ConcurrentTaskRunner>& worker_task_runner,
61  const std::shared_ptr<const fml::SyncSwitch>& is_gpu_disabled_sync_switch)
62  : PlatformViewIOS(delegate,
63  IOSContext::Create(rendering_api,
64  delegate.OnPlatformViewGetSettings().enable_impeller
67  is_gpu_disabled_sync_switch),
68  platform_views_controller,
69  task_runners) {}
70 
72 
73 // |PlatformView|
74 void PlatformViewIOS::HandlePlatformMessage(std::unique_ptr<flutter::PlatformMessage> message) {
75  platform_message_handler_->HandlePlatformMessage(std::move(message));
76 }
77 
79  return owner_controller_;
80 }
81 
83  FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());
84  std::lock_guard<std::mutex> guard(ios_surface_mutex_);
85  if (ios_surface_ || !owner_controller) {
86  NotifyDestroyed();
87  ios_surface_.reset();
88  accessibility_bridge_.Clear();
89  }
90  owner_controller_ = owner_controller;
91 
92  // Add an observer that will clear out the owner_controller_ ivar and
93  // the accessibility_bridge_ in case the view controller is deleted.
94  dealloc_view_controller_observer_.reset([[NSNotificationCenter defaultCenter]
95  addObserverForName:FlutterViewControllerWillDealloc
96  object:owner_controller_
97  queue:[NSOperationQueue mainQueue]
98  usingBlock:^(NSNotification* note) {
99  // Implicit copy of 'this' is fine.
100  accessibility_bridge_.Clear();
101  owner_controller_ = nil;
102  }]);
103 
104  if (owner_controller_ && owner_controller_.isViewLoaded) {
105  this->attachView();
106  }
107  // Do not call `NotifyCreated()` here - let FlutterViewController take care
108  // of that when its Viewport is sized. If `NotifyCreated()` is called here,
109  // it can occasionally get invoked before the viewport is sized resulting in
110  // a framebuffer that will not be able to completely attach.
111 }
112 
114  FML_DCHECK(owner_controller_);
115  FML_DCHECK(owner_controller_.isViewLoaded) << "FlutterViewController's view should be loaded "
116  "before attaching to PlatformViewIOS.";
117  FlutterView* flutter_view = static_cast<FlutterView*>(owner_controller_.view);
118  CALayer* ca_layer = flutter_view.layer;
119  ios_surface_ = IOSSurface::Create(ios_context_, ca_layer);
120  FML_DCHECK(ios_surface_ != nullptr);
121 
122  if (accessibility_bridge_) {
123  accessibility_bridge_.Set(std::make_unique<AccessibilityBridge>(
124  owner_controller_, this, owner_controller_.platformViewsController));
125  }
126 }
127 
128 PointerDataDispatcherMaker PlatformViewIOS::GetDispatcherMaker() {
129  return [](DefaultPointerDataDispatcher::Delegate& delegate) {
130  return std::make_unique<SmoothPointerDataDispatcher>(delegate);
131  };
132 }
133 
135  NSObject<FlutterTexture>* texture) {
136  RegisterTexture(ios_context_->CreateExternalTexture(texture_id, texture));
137 }
138 
139 // |PlatformView|
140 std::unique_ptr<Surface> PlatformViewIOS::CreateRenderingSurface() {
141  FML_DCHECK(task_runners_.GetRasterTaskRunner()->RunsTasksOnCurrentThread());
142  std::lock_guard<std::mutex> guard(ios_surface_mutex_);
143  if (!ios_surface_) {
144  FML_DLOG(INFO) << "Could not CreateRenderingSurface, this PlatformViewIOS "
145  "has no ViewController.";
146  return nullptr;
147  }
148  return ios_surface_->CreateGPUSurface(ios_context_->GetMainContext().get());
149 }
150 
151 // |PlatformView|
152 std::shared_ptr<ExternalViewEmbedder> PlatformViewIOS::CreateExternalViewEmbedder() {
153  return std::make_shared<IOSExternalViewEmbedder>(platform_views_controller_, ios_context_);
154 }
155 
156 // |PlatformView|
157 sk_sp<GrDirectContext> PlatformViewIOS::CreateResourceContext() const {
158  return ios_context_->CreateResourceContext();
159 }
160 
161 // |PlatformView|
162 std::shared_ptr<impeller::Context> PlatformViewIOS::GetImpellerContext() const {
163  return ios_context_->GetImpellerContext();
164 }
165 
166 // |PlatformView|
168  if (!owner_controller_) {
169  FML_LOG(WARNING) << "Could not set semantics to enabled, this "
170  "PlatformViewIOS has no ViewController.";
171  return;
172  }
173  if (enabled && !accessibility_bridge_) {
174  accessibility_bridge_.Set(std::make_unique<AccessibilityBridge>(
175  owner_controller_, this, owner_controller_.platformViewsController));
176  } else if (!enabled && accessibility_bridge_) {
177  accessibility_bridge_.Clear();
178  } else {
179  PlatformView::SetSemanticsEnabled(enabled);
180  }
181 }
182 
183 // |shell:PlatformView|
185  PlatformView::SetAccessibilityFeatures(flags);
186 }
187 
188 // |PlatformView|
189 void PlatformViewIOS::UpdateSemantics(flutter::SemanticsNodeUpdates update,
190  flutter::CustomAccessibilityActionUpdates actions) {
191  FML_DCHECK(owner_controller_);
192  if (accessibility_bridge_) {
193  accessibility_bridge_.get()->UpdateSemantics(std::move(update), actions);
194  [[NSNotificationCenter defaultCenter] postNotificationName:FlutterSemanticsUpdateNotification
195  object:owner_controller_];
196  }
197 }
198 
199 // |PlatformView|
200 std::unique_ptr<VsyncWaiter> PlatformViewIOS::CreateVSyncWaiter() {
201  return std::make_unique<VsyncWaiterIOS>(task_runners_);
202 }
203 
205  if (accessibility_bridge_) {
206  accessibility_bridge_.get()->clearState();
207  }
208  if (!owner_controller_) {
209  return;
210  }
211  [owner_controller_.platformViewsController reset];
212  [owner_controller_.restorationPlugin reset];
213 }
214 
215 std::unique_ptr<std::vector<std::string>> PlatformViewIOS::ComputePlatformResolvedLocales(
216  const std::vector<std::string>& supported_locale_data) {
217  size_t localeDataLength = 3;
218  NSMutableArray<NSString*>* supported_locale_identifiers =
219  [NSMutableArray arrayWithCapacity:supported_locale_data.size() / localeDataLength];
220  for (size_t i = 0; i < supported_locale_data.size(); i += localeDataLength) {
221  NSDictionary<NSString*, NSString*>* dict = @{
222  NSLocaleLanguageCode : [NSString stringWithUTF8String:supported_locale_data[i].c_str()]
223  ?: @"",
224  NSLocaleCountryCode : [NSString stringWithUTF8String:supported_locale_data[i + 1].c_str()]
225  ?: @"",
226  NSLocaleScriptCode : [NSString stringWithUTF8String:supported_locale_data[i + 2].c_str()]
227  ?: @""
228  };
229  [supported_locale_identifiers addObject:[NSLocale localeIdentifierFromComponents:dict]];
230  }
231  NSArray<NSString*>* result =
232  [NSBundle preferredLocalizationsFromArray:supported_locale_identifiers];
233 
234  // Output format should be either empty or 3 strings for language, country, and script.
235  std::unique_ptr<std::vector<std::string>> out = std::make_unique<std::vector<std::string>>();
236 
237  if (result != nullptr && [result count] > 0) {
238  NSLocale* locale = [NSLocale localeWithLocaleIdentifier:[result firstObject]];
239  NSString* languageCode = [locale languageCode];
240  out->emplace_back(languageCode == nullptr ? "" : languageCode.UTF8String);
241  NSString* countryCode = [locale countryCode];
242  out->emplace_back(countryCode == nullptr ? "" : countryCode.UTF8String);
243  NSString* scriptCode = [locale scriptCode];
244  out->emplace_back(scriptCode == nullptr ? "" : scriptCode.UTF8String);
245  }
246  return out;
247 }
248 
249 PlatformViewIOS::ScopedObserver::ScopedObserver() {}
250 
251 PlatformViewIOS::ScopedObserver::~ScopedObserver() {
252  if (observer_) {
253  [[NSNotificationCenter defaultCenter] removeObserver:observer_];
254  }
255 }
256 
257 void PlatformViewIOS::ScopedObserver::reset(id<NSObject> observer) {
258  if (observer != observer_) {
259  if (observer_) {
260  [[NSNotificationCenter defaultCenter] removeObserver:observer_];
261  }
262  observer_ = observer;
263  }
264 }
265 
266 } // namespace flutter
flutter::IOSRenderingBackend::kSkia
@ kSkia
flutter::PlatformViewIOS::ComputePlatformResolvedLocales
std::unique_ptr< std::vector< std::string > > ComputePlatformResolvedLocales(const std::vector< std::string > &supported_locale_data) override
Definition: platform_view_ios.mm:215
flutter::PlatformMessageHandlerIos
Definition: platform_message_handler_ios.h:14
flutter::PlatformViewIOS::CreateResourceContext
sk_sp< GrDirectContext > CreateResourceContext() const override
Definition: platform_view_ios.mm:157
flutter::PlatformViewIOS::CreateExternalViewEmbedder
std::shared_ptr< ExternalViewEmbedder > CreateExternalViewEmbedder() override
Definition: platform_view_ios.mm:152
flutter::PlatformViewIOS::OnPreEngineRestart
void OnPreEngineRestart() const override
Definition: platform_view_ios.mm:204
FlutterViewController
Definition: FlutterViewController.h:57
flutter::PlatformViewIOS::SetOwnerViewController
void SetOwnerViewController(__weak FlutterViewController *owner_controller)
Definition: platform_view_ios.mm:82
FlutterSemanticsUpdateNotification
FLUTTER_DARWIN_EXPORT const NSNotificationName FlutterSemanticsUpdateNotification
Definition: FlutterViewController.mm:43
flutter::PlatformViewIOS::CreateRenderingSurface
std::unique_ptr< Surface > CreateRenderingSurface() override
Definition: platform_view_ios.mm:140
flutter::PlatformViewIOS::HandlePlatformMessage
void HandlePlatformMessage(std::unique_ptr< flutter::PlatformMessage > message) override
Definition: platform_view_ios.mm:74
flutter::PlatformViewIOS::UpdateSemantics
void UpdateSemantics(flutter::SemanticsNodeUpdates update, flutter::CustomAccessibilityActionUpdates actions) override
Definition: platform_view_ios.mm:189
flutter::PlatformViewIOS
Definition: platform_view_ios.h:39
flutter::PlatformViewIOS::GetOwnerViewController
FlutterViewController * GetOwnerViewController() const __attribute__((cf_audited_transfer))
Definition: platform_view_ios.mm:78
flutter::IOSContext
Manages the lifetime of the on-screen and off-screen rendering contexts on iOS. On-screen contexts ar...
Definition: ios_context.h:39
flutter::IOSRenderingBackend
IOSRenderingBackend
Definition: rendering_api_selection.h:19
flutter::IOSRenderingBackend::kImpeller
@ kImpeller
flutter::IOSSurface::Create
static std::unique_ptr< IOSSurface > Create(std::shared_ptr< IOSContext > context, CALayer *layer)
Definition: ios_surface.mm:19
flutter::PlatformViewIOS::~PlatformViewIOS
~PlatformViewIOS() override
FlutterViewControllerWillDealloc
const NSNotificationName FlutterViewControllerWillDealloc
Definition: FlutterViewController.mm:44
flutter
Definition: accessibility_bridge.h:27
flutter::PlatformViewIOS::attachView
void attachView()
Definition: platform_view_ios.mm:113
flutter::IOSRenderingAPI
IOSRenderingAPI
Definition: rendering_api_selection.h:14
flutter::PlatformViewIOS::GetImpellerContext
std::shared_ptr< impeller::Context > GetImpellerContext() const override
Definition: platform_view_ios.mm:162
flutter::PlatformViewIOS::SetAccessibilityFeatures
void SetAccessibilityFeatures(int32_t flags) override
Definition: platform_view_ios.mm:184
FlutterViewController_Internal.h
FlutterPlatformViewsController
Definition: FlutterPlatformViewsController.h:31
FlutterView
Definition: FlutterView.h:33
vsync_waiter_ios.h
flutter::PlatformViewIOS::SetSemanticsEnabled
void SetSemanticsEnabled(bool enabled) override
Definition: platform_view_ios.mm:167
platform_view_ios.h
flutter::PlatformViewIOS::CreateVSyncWaiter
std::unique_ptr< VsyncWaiter > CreateVSyncWaiter() override
Definition: platform_view_ios.mm:200
texture_id
int64_t texture_id
Definition: texture_registrar_unittests.cc:24
flutter::PlatformViewIOS::RegisterExternalTexture
void RegisterExternalTexture(int64_t id, NSObject< FlutterTexture > *texture)
Definition: platform_view_ios.mm:134
flutter::PlatformViewIOS::GetDispatcherMaker
PointerDataDispatcherMaker GetDispatcherMaker() override
Definition: platform_view_ios.mm:128
FLUTTER_ASSERT_ARC
Definition: FlutterChannelKeyResponder.mm:13
flutter::PlatformViewIOS::PlatformViewIOS
PlatformViewIOS(PlatformView::Delegate &delegate, const std::shared_ptr< IOSContext > &context, __weak FlutterPlatformViewsController *platform_views_controller, const flutter::TaskRunners &task_runners)
Definition: platform_view_ios.mm:44