Flutter Windows Embedder
flutter_windows_engine.h
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 #ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_FLUTTER_WINDOWS_ENGINE_H_
6 #define FLUTTER_SHELL_PLATFORM_WINDOWS_FLUTTER_WINDOWS_ENGINE_H_
7 
8 #include <chrono>
9 #include <map>
10 #include <memory>
11 #include <optional>
12 #include <shared_mutex>
13 #include <string>
14 #include <string_view>
15 #include <unordered_map>
16 #include <vector>
17 
18 #include "flutter/fml/closure.h"
19 #include "flutter/fml/macros.h"
25 #include "flutter/shell/platform/embedder/embedder.h"
48 #include "third_party/rapidjson/include/rapidjson/document.h"
49 
50 namespace flutter {
51 
52 // The implicit view's ID.
53 //
54 // See:
55 // https://api.flutter-io.cn/flutter/dart-ui/PlatformDispatcher/implicitView.html
57 
58 class FlutterWindowsView;
60 
61 // Update the thread priority for the Windows engine.
63  FlutterThreadPriority priority) {
64  // TODO(99502): Add support for tracing to the windows embedding so we can
65  // mark thread priorities and success/failure.
66  switch (priority) {
67  case FlutterThreadPriority::kBackground: {
68  SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL);
69  break;
70  }
71  case FlutterThreadPriority::kDisplay: {
72  SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
73  break;
74  }
75  case FlutterThreadPriority::kRaster: {
76  SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
77  break;
78  }
79  case FlutterThreadPriority::kNormal: {
80  // For normal or default priority we do not need to set the priority
81  // class.
82  break;
83  }
84  }
85 }
86 
87 // Manages state associated with the underlying FlutterEngine that isn't
88 // related to its display.
89 //
90 // In most cases this will be associated with a FlutterView, but if not will
91 // run in headless mode.
93  public:
94  // Creates a new Flutter engine object configured to run |project|.
96  const FlutterProjectBundle& project,
97  std::shared_ptr<WindowsProcTable> windows_proc_table = nullptr);
98 
99  virtual ~FlutterWindowsEngine();
100 
101  // Returns the engine associated with the given identifier.
102  // The engine_id must be valid and for a running engine, otherwise
103  // the behavior is undefined.
104  // Must be called on the platform thread.
105  static FlutterWindowsEngine* GetEngineForId(int64_t engine_id);
106 
107  // Starts running the entrypoint function specifed in the project bundle. If
108  // unspecified, defaults to main().
109  //
110  // Returns false if the engine couldn't be started.
111  bool Run();
112 
113  // Starts running the engine with the given entrypoint. If the empty string
114  // is specified, defaults to the entrypoint function specified in the project
115  // bundle, or main() if both are unspecified.
116  //
117  // Returns false if the engine couldn't be started or if conflicting,
118  // non-default values are passed here and in the project bundle..
119  //
120  // DEPRECATED: Prefer setting the entrypoint in the FlutterProjectBundle
121  // passed to the constructor and calling the no-parameter overload.
122  bool Run(std::string_view entrypoint);
123 
124  // Returns true if the engine is currently running.
125  virtual bool running() const { return engine_ != nullptr; }
126 
127  // Stops the engine. This invalidates the pointer returned by engine().
128  //
129  // Returns false if stopping the engine fails, or if it was not running.
130  virtual bool Stop();
131 
132  // Create a view that can display this engine's content.
133  //
134  // Returns null on failure.
135  std::unique_ptr<FlutterWindowsView> CreateView(
136  std::unique_ptr<WindowBindingHandler> window,
137  bool is_sized_to_content,
138  const BoxConstraints& box_constraints,
139  FlutterWindowsViewSizingDelegate* sizing_delegate = nullptr);
140 
141  // Remove a view. The engine will no longer render into it.
142  virtual void RemoveView(FlutterViewId view_id);
143 
144  // Get a view that displays this engine's content.
145  //
146  // Returns null if the view does not exist.
147  FlutterWindowsView* view(FlutterViewId view_id) const;
148 
149  // Returns the currently configured Plugin Registrar.
151 
152  // Registers |callback| to be called when the plugin registrar is destroyed.
156 
157  // Sets switches member to the given switches.
158  void SetSwitches(const std::vector<std::string>& switches);
159 
160  FlutterDesktopMessengerRef messenger() { return messenger_->ToRef(); }
161 
163  return message_dispatcher_.get();
164  }
165 
166  std::shared_ptr<DisplayManagerWin32> display_manager() {
167  return display_manager_;
168  }
169 
170  // Notifies the engine about a display update.
171  void UpdateDisplay(const std::vector<FlutterEngineDisplay>& displays);
172 
173  TaskRunner* task_runner() { return task_runner_.get(); }
174 
175  BinaryMessenger* messenger_wrapper() { return messenger_wrapper_.get(); }
176 
178  return texture_registrar_.get();
179  }
180 
181  // The EGL manager object. If this is nullptr, then we are
182  // rendering using software instead of OpenGL.
183  egl::Manager* egl_manager() const { return egl_manager_.get(); }
184 
186  return window_proc_delegate_manager_.get();
187  }
188 
189  // Informs the engine that the window metrics have changed.
190  void SendWindowMetricsEvent(const FlutterWindowMetricsEvent& event);
191 
192  // Informs the engine of an incoming pointer event.
193  void SendPointerEvent(const FlutterPointerEvent& event);
194 
195  // Informs the engine of an incoming key event.
196  void SendKeyEvent(const FlutterKeyEvent& event,
197  FlutterKeyEventCallback callback,
198  void* user_data);
199 
200  // Informs the engine of an incoming focus event.
201  void SendViewFocusEvent(const FlutterViewFocusEvent& event);
202 
204  return keyboard_key_handler_.get();
205  }
206  TextInputPlugin* text_input_plugin() { return text_input_plugin_.get(); }
207 
208  // Sends the given message to the engine, calling |reply| with |user_data|
209  // when a response is received from the engine if they are non-null.
210  bool SendPlatformMessage(const char* channel,
211  const uint8_t* message,
212  const size_t message_size,
213  const FlutterDesktopBinaryReply reply,
214  void* user_data);
215 
216  // Sends the given data as the response to an earlier platform message.
219  const uint8_t* data,
220  size_t data_length);
221 
222  // Callback passed to Flutter engine for notifying window of platform
223  // messages.
224  void HandlePlatformMessage(const FlutterPlatformMessage*);
225 
226  // Informs the engine that the system font list has changed.
227  void ReloadSystemFonts();
228 
229  // Informs the engine that a new frame is needed to redraw the content.
230  void ScheduleFrame();
231 
232  // Set the callback that is called when the next frame is drawn.
233  void SetNextFrameCallback(fml::closure callback);
234 
235  // Attempts to register the texture with the given |texture_id|.
236  bool RegisterExternalTexture(int64_t texture_id);
237 
238  // Attempts to unregister the texture with the given |texture_id|.
240 
241  // Notifies the engine about a new frame being available for the
242  // given |texture_id|.
244 
245  // Posts the given callback onto the raster thread.
246  virtual bool PostRasterThreadTask(fml::closure callback) const;
247 
248  // Invoke on the embedder's vsync callback to schedule a frame.
249  void OnVsync(intptr_t baton);
250 
251  // Dispatches a semantics action to the specified semantics node.
253  uint64_t node_id,
254  FlutterSemanticsAction action,
255  fml::MallocMapping data);
256 
257  // Informs the engine that the semantics enabled state has changed.
258  void UpdateSemanticsEnabled(bool enabled);
259 
260  // Returns true if the semantics tree is enabled.
261  bool semantics_enabled() const { return semantics_enabled_; }
262 
263  bool iaccessibleex_enabled() const {
264  return project_->accessibility_mode() ==
266  }
267 
268  // Refresh accessibility features and send them to the engine.
270 
271  // Refresh high contrast accessibility mode and notify the engine.
272  void UpdateHighContrastMode();
273 
274  // Returns true if the high contrast feature is enabled.
275  bool high_contrast_enabled() const { return high_contrast_enabled_; }
276 
277  // Register a root isolate create callback.
278  //
279  // The root isolate create callback is invoked at creation of the root Dart
280  // isolate in the app. This may be used to be notified that execution of the
281  // main Dart entrypoint is about to begin, and is used by test infrastructure
282  // to register a native function resolver that can register and resolve
283  // functions marked as native in the Dart code.
284  //
285  // This must be called before calling |Run|.
286  void SetRootIsolateCreateCallback(const fml::closure& callback) {
287  root_isolate_create_callback_ = callback;
288  }
289 
290  // Returns the executable name for this process or "Flutter" if unknown.
291  std::string GetExecutableName() const;
292 
293  // Called when the application quits in response to a quit request.
294  void OnQuit(std::optional<HWND> hwnd,
295  std::optional<WPARAM> wparam,
296  std::optional<LPARAM> lparam,
297  UINT exit_code);
298 
299  // Called when a WM_CLOSE message is received.
300  void RequestApplicationQuit(HWND hwnd,
301  WPARAM wparam,
302  LPARAM lparam,
303  AppExitType exit_type);
304 
305  // Called when a WM_DWMCOMPOSITIONCHANGED message is received.
307 
308  // Called when a Window receives an event that may alter the application
309  // lifecycle state.
310  void OnWindowStateEvent(HWND hwnd, WindowStateEvent event);
311 
312  // Handle a message from a non-Flutter window in the same application.
313  // Returns a result when the message is consumed and should not be processed
314  // further.
315  std::optional<LRESULT> ProcessExternalWindowMessage(HWND hwnd,
316  UINT message,
317  WPARAM wparam,
318  LPARAM lparam);
319 
321  return lifecycle_manager_.get();
322  }
323 
324  std::shared_ptr<WindowsProcTable> windows_proc_table() {
325  return windows_proc_table_;
326  }
327 
328  // Sets the cursor that should be used when the mouse is over the Flutter
329  // content. See mouse_cursor.dart for the values and meanings of cursor_name.
330  void UpdateFlutterCursor(const std::string& cursor_name) const;
331 
332  // Sets the cursor directly from a cursor handle.
333  void SetFlutterCursor(HCURSOR cursor) const;
334 
335  WindowManager* window_manager() { return window_manager_.get(); }
336 
337  // Returns the root view associated with the top-level window with |hwnd| as
338  // the window handle or nullptr if no such view could be found.
340 
341  protected:
342  // Creates the keyboard key handler.
343  //
344  // Exposing this method allows unit tests to override in order to
345  // capture information.
346  virtual std::unique_ptr<KeyboardHandlerBase> CreateKeyboardKeyHandler(
350 
351  // Creates the text input plugin.
352  //
353  // Exposing this method allows unit tests to override in order to
354  // capture information.
355  virtual std::unique_ptr<TextInputPlugin> CreateTextInputPlugin(
357 
358  // Invoked by the engine right before the engine is restarted.
359  //
360  // This should reset necessary states to as if the engine has just been
361  // created. This is typically caused by a hot restart (Shift-R in CLI.)
362  void OnPreEngineRestart();
363 
364  // Invoked by the engine when a listener is set or cleared on a platform
365  // channel.
366  virtual void OnChannelUpdate(std::string name, bool listening);
367 
368  virtual void OnViewFocusChangeRequest(
369  const FlutterViewFocusChangeRequest* request);
370 
371  private:
372  // Allows swapping out embedder_api_ calls in tests.
373  friend class EngineModifier;
374 
375  // Maps a Flutter cursor name to an HCURSOR.
376  //
377  // Returns the arrow cursor for unknown constants.
378  //
379  // This map must be kept in sync with Flutter framework's
380  // services/mouse_cursor.dart.
381  HCURSOR GetCursorByName(const std::string& cursor_name) const;
382 
383  // Sends system locales to the engine.
384  //
385  // Should be called just after the engine is run, and after any relevant
386  // system changes.
387  void SendSystemLocales();
388 
389  // Create the keyboard & text input sub-systems.
390  //
391  // This requires that a view is attached to the engine.
392  // Calling this method again resets the keyboard state.
393  void InitializeKeyboard();
394 
395  // Send the currently enabled accessibility features to the engine.
396  void SendAccessibilityFeatures();
397 
398  // Present content to a view. Returns true if the content was presented.
399  //
400  // This is invoked on the raster thread.
401  bool Present(const FlutterPresentViewInfo* info);
402 
403  // The handle to the embedder.h engine instance.
404  FLUTTER_API_SYMBOL(FlutterEngine) engine_ = nullptr;
405 
406  FlutterEngineProcTable embedder_api_ = {};
407 
408  std::unique_ptr<FlutterProjectBundle> project_;
409 
410  // AOT data, if any.
411  UniqueAotDataPtr aot_data_;
412 
413  // The ID that the next view will have.
414  FlutterViewId next_view_id_ = kImplicitViewId;
415 
416  // The views displaying the content running in this engine, if any.
417  //
418  // This is read and mutated by the platform thread. This is read by the raster
419  // thread to present content to a view.
420  //
421  // Reads to this object on non-platform threads must be protected
422  // by acquiring a shared lock on |views_mutex_|.
423  //
424  // Writes to this object must only happen on the platform thread
425  // and must be protected by acquiring an exclusive lock on |views_mutex_|.
426  std::unordered_map<FlutterViewId, FlutterWindowsView*> views_;
427 
428  // The mutex that protects the |views_| map.
429  //
430  // The raster thread acquires a shared lock to present to a view.
431  //
432  // The platform thread acquires a shared lock to access the view.
433  // The platform thread acquires an exclusive lock before adding
434  // a view to the engine or after removing a view from the engine.
435  mutable std::shared_mutex views_mutex_;
436 
437  // The display monitor.
438  std::shared_ptr<DisplayManagerWin32> display_manager_;
439 
440  // Task runner for tasks posted from the engine.
441  std::unique_ptr<TaskRunner> task_runner_;
442 
443  // The plugin messenger handle given to API clients.
444  fml::RefPtr<flutter::FlutterDesktopMessenger> messenger_;
445 
446  // A wrapper around messenger_ for interacting with client_wrapper-level APIs.
447  std::unique_ptr<BinaryMessengerImpl> messenger_wrapper_;
448 
449  // Message dispatch manager for messages from engine_.
450  std::unique_ptr<IncomingMessageDispatcher> message_dispatcher_;
451 
452  // The plugin registrar handle given to API clients.
453  std::unique_ptr<FlutterDesktopPluginRegistrar> plugin_registrar_;
454 
455  // The texture registrar.
456  std::unique_ptr<FlutterWindowsTextureRegistrar> texture_registrar_;
457 
458  // An object used for intializing ANGLE and creating / destroying render
459  // surfaces. If nullptr, ANGLE failed to initialize and software rendering
460  // should be used instead.
461  std::unique_ptr<egl::Manager> egl_manager_;
462 
463  // The compositor that creates backing stores for the engine to render into
464  // and then presents them onto views.
465  std::unique_ptr<Compositor> compositor_;
466 
467  // The plugin registrar managing internal plugins.
468  std::unique_ptr<PluginRegistrar> internal_plugin_registrar_;
469 
470  // Handler for accessibility events.
471  std::unique_ptr<AccessibilityPlugin> accessibility_plugin_;
472 
473  // Handler for cursor events.
474  std::unique_ptr<CursorHandler> cursor_handler_;
475 
476  // Handler for the flutter/platform channel.
477  std::unique_ptr<PlatformHandler> platform_handler_;
478 
479  // Handlers for keyboard events from Windows.
480  std::unique_ptr<KeyboardHandlerBase> keyboard_key_handler_;
481 
482  // The manager that manages the lifecycle of |HostWindow|s, native
483  // Win32 windows hosting a Flutter view in their client area.
484  std::unique_ptr<WindowManager> window_manager_;
485 
486  // Handlers for text events from Windows.
487  std::unique_ptr<TextInputPlugin> text_input_plugin_;
488 
489  // The settings plugin.
490  std::unique_ptr<SettingsPlugin> settings_plugin_;
491 
492  // Callbacks to be called when the engine (and thus the plugin registrar) is
493  // being destroyed.
496  plugin_registrar_destruction_callbacks_;
497 
498  // The approximate time between vblank events.
499  std::chrono::nanoseconds FrameInterval();
500 
501  // The start time used to align frames.
502  std::chrono::nanoseconds start_time_ = std::chrono::nanoseconds::zero();
503 
504  // An override of the frame interval used by EngineModifier for testing.
505  std::optional<std::chrono::nanoseconds> frame_interval_override_ =
506  std::nullopt;
507 
508  bool semantics_enabled_ = false;
509 
510  bool high_contrast_enabled_ = false;
511 
512  bool enable_impeller_ = false;
513 
514  // The manager for WindowProc delegate registration and callbacks.
515  std::unique_ptr<WindowProcDelegateManager> window_proc_delegate_manager_;
516 
517  // The root isolate creation callback.
518  fml::closure root_isolate_create_callback_;
519 
520  // The on frame drawn callback.
521  fml::closure next_frame_callback_;
522 
523  // Handler for top level window messages.
524  std::unique_ptr<WindowsLifecycleManager> lifecycle_manager_;
525 
526  std::shared_ptr<WindowsProcTable> windows_proc_table_;
527 
528  std::shared_ptr<egl::ProcTable> gl_;
529 
530  std::unique_ptr<PlatformViewPlugin> platform_view_plugin_;
531 
532  // Handles display-related window messages.
533  bool HandleDisplayMonitorMessage(HWND hwnd,
534  UINT message,
535  WPARAM wparam,
536  LPARAM lparam,
537  LRESULT* result);
538 
539  FML_DISALLOW_COPY_AND_ASSIGN(FlutterWindowsEngine);
540 };
541 
542 } // namespace flutter
543 
544 #endif // FLUTTER_SHELL_PLATFORM_WINDOWS_FLUTTER_WINDOWS_ENGINE_H_
FlutterWindowsTextureRegistrar * texture_registrar()
std::shared_ptr< WindowsProcTable > windows_proc_table()
FlutterWindowsEngine(const FlutterProjectBundle &project, std::shared_ptr< WindowsProcTable > windows_proc_table=nullptr)
FlutterDesktopMessengerRef messenger()
WindowsLifecycleManager * lifecycle_manager()
void OnWindowStateEvent(HWND hwnd, WindowStateEvent event)
void RequestApplicationQuit(HWND hwnd, WPARAM wparam, LPARAM lparam, AppExitType exit_type)
WindowProcDelegateManager * window_proc_delegate_manager()
FlutterWindowsView * view(FlutterViewId view_id) const
std::shared_ptr< DisplayManagerWin32 > display_manager()
void SendViewFocusEvent(const FlutterViewFocusEvent &event)
bool SendPlatformMessage(const char *channel, const uint8_t *message, const size_t message_size, const FlutterDesktopBinaryReply reply, void *user_data)
virtual void OnViewFocusChangeRequest(const FlutterViewFocusChangeRequest *request)
std::optional< LRESULT > ProcessExternalWindowMessage(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
void AddPluginRegistrarDestructionCallback(FlutterDesktopOnPluginRegistrarDestroyed callback, FlutterDesktopPluginRegistrarRef registrar)
bool RegisterExternalTexture(int64_t texture_id)
void UpdateDisplay(const std::vector< FlutterEngineDisplay > &displays)
void SendPlatformMessageResponse(const FlutterDesktopMessageResponseHandle *handle, const uint8_t *data, size_t data_length)
void SetRootIsolateCreateCallback(const fml::closure &callback)
static FlutterWindowsEngine * GetEngineForId(int64_t engine_id)
std::unique_ptr< FlutterWindowsView > CreateView(std::unique_ptr< WindowBindingHandler > window, bool is_sized_to_content, const BoxConstraints &box_constraints, FlutterWindowsViewSizingDelegate *sizing_delegate=nullptr)
virtual void OnChannelUpdate(std::string name, bool listening)
virtual std::unique_ptr< KeyboardHandlerBase > CreateKeyboardKeyHandler(BinaryMessenger *messenger, KeyboardKeyEmbedderHandler::GetKeyStateHandler get_key_state, KeyboardKeyEmbedderHandler::MapVirtualKeyToScanCode map_vk_to_scan)
bool DispatchSemanticsAction(FlutterViewId view_id, uint64_t node_id, FlutterSemanticsAction action, fml::MallocMapping data)
bool MarkExternalTextureFrameAvailable(int64_t texture_id)
FlutterWindowsView * GetViewFromTopLevelWindow(HWND hwnd) const
KeyboardHandlerBase * keyboard_key_handler()
virtual bool PostRasterThreadTask(fml::closure callback) const
IncomingMessageDispatcher * message_dispatcher()
bool UnregisterExternalTexture(int64_t texture_id)
void SetNextFrameCallback(fml::closure callback)
void HandlePlatformMessage(const FlutterPlatformMessage *)
virtual void RemoveView(FlutterViewId view_id)
FlutterDesktopPluginRegistrarRef GetRegistrar()
virtual std::unique_ptr< TextInputPlugin > CreateTextInputPlugin(BinaryMessenger *messenger)
void UpdateFlutterCursor(const std::string &cursor_name) const
void SetFlutterCursor(HCURSOR cursor) const
void SendPointerEvent(const FlutterPointerEvent &event)
void SendWindowMetricsEvent(const FlutterWindowMetricsEvent &event)
void SetSwitches(const std::vector< std::string > &switches)
void SendKeyEvent(const FlutterKeyEvent &event, FlutterKeyEventCallback callback, void *user_data)
void OnQuit(std::optional< HWND > hwnd, std::optional< WPARAM > wparam, std::optional< LPARAM > lparam, UINT exit_code)
std::function< SHORT(UINT, bool)> MapVirtualKeyToScanCode
uint32_t texture_id
std::vector< FlutterEngineDisplay > * displays
void(* FlutterDesktopBinaryReply)(const uint8_t *data, size_t data_size, void *user_data)
struct FlutterDesktopMessenger * FlutterDesktopMessengerRef
struct _FlutterPlatformMessageResponseHandle FlutterDesktopMessageResponseHandle
void(* FlutterDesktopOnPluginRegistrarDestroyed)(FlutterDesktopPluginRegistrarRef)
FlutterDesktopBinaryReply callback
Win32Message message
WindowStateEvent
An event representing a change in window state that may update the.
int64_t FlutterViewId
static void WindowsPlatformThreadPrioritySetter(FlutterThreadPriority priority)
constexpr FlutterViewId kImplicitViewId
std::unique_ptr< _FlutterEngineAOTData, FlutterEngineCollectAOTDataFnPtr > UniqueAotDataPtr