Flutter Engine
flutter_windows_engine.cc
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 #include "flutter/shell/platform/windows/flutter_windows_engine.h"
6 
7 #include <filesystem>
8 #include <iostream>
9 #include <sstream>
10 
11 #include "flutter/shell/platform/common/cpp/path_utils.h"
12 #include "flutter/shell/platform/windows/flutter_windows_view.h"
13 #include "flutter/shell/platform/windows/string_conversion.h"
14 #include "flutter/shell/platform/windows/system_utils.h"
15 
16 namespace flutter {
17 
18 namespace {
19 
20 // Creates and returns a FlutterRendererConfig that renders to the view (if any)
21 // of a FlutterWindowsEngine, which should be the user_data received by the
22 // render callbacks.
23 FlutterRendererConfig GetRendererConfig() {
24  FlutterRendererConfig config = {};
25  config.type = kOpenGL;
26  config.open_gl.struct_size = sizeof(config.open_gl);
27  config.open_gl.make_current = [](void* user_data) -> bool {
28  auto host = static_cast<FlutterWindowsEngine*>(user_data);
29  if (!host->view()) {
30  return false;
31  }
32  return host->view()->MakeCurrent();
33  };
34  config.open_gl.clear_current = [](void* user_data) -> bool {
35  auto host = static_cast<FlutterWindowsEngine*>(user_data);
36  if (!host->view()) {
37  return false;
38  }
39  return host->view()->ClearContext();
40  };
41  config.open_gl.present = [](void* user_data) -> bool {
42  auto host = static_cast<FlutterWindowsEngine*>(user_data);
43  if (!host->view()) {
44  return false;
45  }
46  return host->view()->SwapBuffers();
47  };
48  config.open_gl.fbo_callback = [](void* user_data) -> uint32_t { return 0; };
49  config.open_gl.gl_proc_resolver = [](void* user_data,
50  const char* what) -> void* {
51  return reinterpret_cast<void*>(eglGetProcAddress(what));
52  };
53  config.open_gl.make_resource_current = [](void* user_data) -> bool {
54  auto host = static_cast<FlutterWindowsEngine*>(user_data);
55  if (!host->view()) {
56  return false;
57  }
58  return host->view()->MakeResourceCurrent();
59  };
60  return config;
61 }
62 
63 // Converts a FlutterPlatformMessage to an equivalent FlutterDesktopMessage.
65  const FlutterPlatformMessage& engine_message) {
66  FlutterDesktopMessage message = {};
67  message.struct_size = sizeof(message);
68  message.channel = engine_message.channel;
69  message.message = engine_message.message;
70  message.message_size = engine_message.message_size;
71  message.response_handle = engine_message.response_handle;
72  return message;
73 }
74 
75 // Converts a LanguageInfo struct to a FlutterLocale struct. |info| must outlive
76 // the returned value, since the returned FlutterLocale has pointers into it.
77 FlutterLocale CovertToFlutterLocale(const LanguageInfo& info) {
78  FlutterLocale locale = {};
79  locale.struct_size = sizeof(FlutterLocale);
80  locale.language_code = info.language.c_str();
81  if (!info.region.empty()) {
82  locale.country_code = info.region.c_str();
83  }
84  if (!info.script.empty()) {
85  locale.script_code = info.script.c_str();
86  }
87  return locale;
88 }
89 
90 } // namespace
91 
93  : project_(std::make_unique<FlutterProjectBundle>(project)) {
94  task_runner_ = std::make_unique<Win32TaskRunner>(
95  GetCurrentThreadId(), [this](const auto* task) {
96  if (!engine_) {
97  std::cerr << "Cannot post an engine task when engine is not running."
98  << std::endl;
99  return;
100  }
101  if (FlutterEngineRunTask(engine_, task) != kSuccess) {
102  std::cerr << "Failed to post an engine task." << std::endl;
103  }
104  });
105 
106  // Set up the legacy structs backing the API handles.
107  messenger_ = std::make_unique<FlutterDesktopMessenger>();
108  messenger_->engine = this;
109  plugin_registrar_ = std::make_unique<FlutterDesktopPluginRegistrar>();
110  plugin_registrar_->engine = this;
111 
112  message_dispatcher_ =
113  std::make_unique<IncomingMessageDispatcher>(messenger_.get());
114  window_proc_delegate_manager_ =
115  std::make_unique<Win32WindowProcDelegateManager>();
116 }
117 
119  Stop();
120 }
121 
122 bool FlutterWindowsEngine::RunWithEntrypoint(const char* entrypoint) {
123  if (!project_->HasValidPaths()) {
124  std::cerr << "Missing or unresolvable paths to assets." << std::endl;
125  return false;
126  }
127  std::string assets_path_string = project_->assets_path().u8string();
128  std::string icu_path_string = project_->icu_path().u8string();
130  aot_data_ = project_->LoadAotData();
131  if (!aot_data_) {
132  std::cerr << "Unable to start engine without AOT data." << std::endl;
133  return false;
134  }
135  }
136 
137  // FlutterProjectArgs is expecting a full argv, so when processing it for
138  // flags the first item is treated as the executable and ignored. Add a dummy
139  // value so that all provided arguments are used.
140  std::vector<std::string> switches = project_->GetSwitches();
141  std::vector<const char*> argv = {"placeholder"};
143  switches.begin(), switches.end(), std::back_inserter(argv),
144  [](const std::string& arg) -> const char* { return arg.c_str(); });
145 
146  const std::vector<std::string>& entrypoint_args =
147  project_->dart_entrypoint_arguments();
148  std::vector<const char*> entrypoint_argv;
150  entrypoint_args.begin(), entrypoint_args.end(),
151  std::back_inserter(entrypoint_argv),
152  [](const std::string& arg) -> const char* { return arg.c_str(); });
153 
154  // Configure task runners.
155  FlutterTaskRunnerDescription platform_task_runner = {};
156  platform_task_runner.struct_size = sizeof(FlutterTaskRunnerDescription);
157  platform_task_runner.user_data = task_runner_.get();
158  platform_task_runner.runs_task_on_current_thread_callback =
159  [](void* user_data) -> bool {
160  return static_cast<Win32TaskRunner*>(user_data)->RunsTasksOnCurrentThread();
161  };
162  platform_task_runner.post_task_callback = [](FlutterTask task,
163  uint64_t target_time_nanos,
164  void* user_data) -> void {
165  static_cast<Win32TaskRunner*>(user_data)->PostTask(task, target_time_nanos);
166  };
167  FlutterCustomTaskRunners custom_task_runners = {};
168  custom_task_runners.struct_size = sizeof(FlutterCustomTaskRunners);
169  custom_task_runners.platform_task_runner = &platform_task_runner;
170 
172  args.struct_size = sizeof(FlutterProjectArgs);
173  args.assets_path = assets_path_string.c_str();
174  args.icu_data_path = icu_path_string.c_str();
175  args.command_line_argc = static_cast<int>(argv.size());
176  args.command_line_argv = argv.size() > 0 ? argv.data() : nullptr;
177  args.dart_entrypoint_argc = static_cast<int>(entrypoint_argv.size());
178  args.dart_entrypoint_argv =
179  entrypoint_argv.size() > 0 ? entrypoint_argv.data() : nullptr;
181  [](const FlutterPlatformMessage* engine_message,
182  void* user_data) -> void {
183  auto host = static_cast<FlutterWindowsEngine*>(user_data);
184  return host->HandlePlatformMessage(engine_message);
185  };
186  args.custom_task_runners = &custom_task_runners;
187  if (aot_data_) {
188  args.aot_data = aot_data_.get();
189  }
190  if (entrypoint) {
191  args.custom_dart_entrypoint = entrypoint;
192  }
193 
194  FlutterRendererConfig renderer_config = GetRendererConfig();
195 
196  auto result = FlutterEngineRun(FLUTTER_ENGINE_VERSION, &renderer_config,
197  &args, this, &engine_);
198  if (result != kSuccess || engine_ == nullptr) {
199  std::cerr << "Failed to start Flutter engine: error " << result
200  << std::endl;
201  return false;
202  }
203 
204  SendSystemSettings();
205 
206  return true;
207 }
208 
210  if (engine_) {
211  if (plugin_registrar_destruction_callback_) {
212  plugin_registrar_destruction_callback_(plugin_registrar_.get());
213  }
214  FlutterEngineResult result = FlutterEngineShutdown(engine_);
215  engine_ = nullptr;
216  return (result == kSuccess);
217  }
218  return false;
219 }
220 
222  view_ = view;
223 }
224 
225 // Returns the currently configured Plugin Registrar.
227  return plugin_registrar_.get();
228 }
229 
232  plugin_registrar_destruction_callback_ = callback;
233 }
234 
236  const FlutterPlatformMessage* engine_message) {
237  if (engine_message->struct_size != sizeof(FlutterPlatformMessage)) {
238  std::cerr << "Invalid message size received. Expected: "
239  << sizeof(FlutterPlatformMessage) << " but received "
240  << engine_message->struct_size << std::endl;
241  return;
242  }
243 
244  auto message = ConvertToDesktopMessage(*engine_message);
245 
246  message_dispatcher_->HandleMessage(
247  message, [this] {}, [this] {});
248 }
249 
250 void FlutterWindowsEngine::SendSystemSettings() {
251  std::vector<LanguageInfo> languages = GetPreferredLanguageInfo();
252  std::vector<FlutterLocale> flutter_locales;
253  flutter_locales.reserve(languages.size());
254  for (const auto& info : languages) {
255  flutter_locales.push_back(CovertToFlutterLocale(info));
256  }
257  // Convert the locale list to the locale pointer list that must be provided.
258  std::vector<const FlutterLocale*> flutter_locale_list;
259  flutter_locale_list.reserve(flutter_locales.size());
261  flutter_locales.begin(), flutter_locales.end(),
262  std::back_inserter(flutter_locale_list),
263  [](const auto& arg) -> const auto* { return &arg; });
264  FlutterEngineUpdateLocales(engine_, flutter_locale_list.data(),
265  flutter_locale_list.size());
266 
267  // TODO: Send 'flutter/settings' channel settings here as well.
268 }
269 
270 } // namespace flutter
size_t struct_size
This size of this struct. Must be sizeof(FlutterLocale).
Definition: embedder.h:944
G_BEGIN_DECLS FlValue * args
void SetPluginRegistrarDestructionCallback(FlutterDesktopOnPluginRegistrarDestroyed callback)
const char * channel
Definition: embedder.h:567
FlutterEngineResult FlutterEngineRunTask(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterTask *task)
Inform the engine to run the specified task. This task has been given to the engine via the FlutterTa...
Definition: embedder.cc:1717
const char * icu_data_path
Definition: embedder.h:1199
const FlutterPlatformMessageResponseHandle * response_handle
Definition: embedder.h:576
size_t struct_size
The size of this struct. Must be sizeof(FlutterTaskRunnerDescription).
Definition: embedder.h:722
const FlutterCustomTaskRunners * custom_task_runners
Definition: embedder.h:1313
void(*)(void) eglGetProcAddress(const char *procname)
Definition: mock_egl.cc:258
Definition: ref_ptr.h:252
FlutterEngineResult FlutterEngineShutdown(FLUTTER_API_SYMBOL(FlutterEngine) engine)
Shuts down a Flutter engine instance. The engine handle is no longer valid for any calls in the embed...
Definition: embedder.cc:1218
const FlutterDesktopMessageResponseHandle * response_handle
FlutterWindowsEngine(const FlutterProjectBundle &project)
FlutterPlatformMessageCallback platform_message_callback
Definition: embedder.h:1222
bool RunWithEntrypoint(const char *entrypoint)
const char *const * command_line_argv
Definition: embedder.h:1217
FlutterDesktopPluginRegistrarRef GetRegistrar()
const char * script_code
Definition: embedder.h:958
const char * country_code
Definition: embedder.h:953
const char *const * dart_entrypoint_argv
Definition: embedder.h:1386
G_BEGIN_DECLS FlValue gpointer user_data
#define FLUTTER_ENGINE_VERSION
Definition: embedder.h:63
FlutterRendererType type
Definition: embedder.h:448
FlutterEngineResult FlutterEngineRun(size_t version, const FlutterRendererConfig *config, const FlutterProjectArgs *args, void *user_data, FLUTTER_API_SYMBOL(FlutterEngine) *engine_out)
Initialize and run a Flutter engine instance and return a handle to it. This is a convenience method ...
Definition: embedder.cc:718
const uint8_t * message
Definition: embedder.h:568
size_t struct_size
The size of this struct. Must be sizeof(FlutterOpenGLRendererConfig).
Definition: embedder.h:379
FlutterEngineResult FlutterEngineUpdateLocales(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterLocale **locales, size_t locales_count)
Notify a running engine instance that the locale has been updated. The preferred locale must be the f...
Definition: embedder.cc:1761
BoolCallback make_resource_current
Definition: embedder.h:398
static FlutterDesktopMessage ConvertToDesktopMessage(const FlutterPlatformMessage &engine_message)
BoolCallback clear_current
Definition: embedder.h:381
const uint8_t * message
const char * custom_dart_entrypoint
Definition: embedder.h:1308
const char * assets_path
Definition: embedder.h:1175
BoolCallback make_current
Definition: embedder.h:380
FlutterOpenGLRendererConfig open_gl
Definition: embedder.h:450
std::vector< LanguageInfo > GetPreferredLanguageInfo()
FlutterEngineResult
Definition: embedder.h:65
size_t struct_size
The size of this struct. Must be sizeof(FlutterProjectArgs).
Definition: embedder.h:1171
UIntCallback fbo_callback
Definition: embedder.h:391
const FlutterTaskRunnerDescription * platform_task_runner
Definition: embedder.h:752
void HandlePlatformMessage(const FlutterPlatformMessage *)
void(* FlutterDesktopOnPluginRegistrarDestroyed)(FlutterDesktopPluginRegistrarRef)
FlutterEngineAOTData aot_data
Definition: embedder.h:1363
ProcResolver gl_proc_resolver
Definition: embedder.h:415
size_t struct_size
The size of this struct. Must be sizeof(FlutterCustomTaskRunners).
Definition: embedder.h:747
size_t struct_size
The size of this struct. Must be sizeof(FlutterPlatformMessage).
Definition: embedder.h:566
const char * language_code
Definition: embedder.h:948
bool FlutterEngineRunsAOTCompiledDartCode(void)
Returns if the Flutter engine instance will run AOT compiled Dart code. This call has no threading re...
Definition: embedder.cc:1821
void SetView(FlutterWindowsView *view)
int command_line_argc
The command line argument count used to initialize the project.
Definition: embedder.h:1201