|  | // Copyright 2013 The Flutter Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_FLUTTER_WINDOWS_ENGINE_H_ | 
|  | #define FLUTTER_SHELL_PLATFORM_WINDOWS_FLUTTER_WINDOWS_ENGINE_H_ | 
|  |  | 
|  | #include <chrono> | 
|  | #include <map> | 
|  | #include <memory> | 
|  | #include <optional> | 
|  | #include <string> | 
|  | #include <string_view> | 
|  | #include <unordered_map> | 
|  | #include <vector> | 
|  |  | 
|  | #include "flutter/fml/closure.h" | 
|  | #include "flutter/fml/macros.h" | 
|  | #include "flutter/fml/synchronization/shared_mutex.h" | 
|  | #include "flutter/shell/platform/common/accessibility_bridge.h" | 
|  | #include "flutter/shell/platform/common/app_lifecycle_state.h" | 
|  | #include "flutter/shell/platform/common/client_wrapper/binary_messenger_impl.h" | 
|  | #include "flutter/shell/platform/common/client_wrapper/include/flutter/basic_message_channel.h" | 
|  | #include "flutter/shell/platform/common/incoming_message_dispatcher.h" | 
|  | #include "flutter/shell/platform/embedder/embedder.h" | 
|  | #include "flutter/shell/platform/windows/accessibility_bridge_windows.h" | 
|  | #include "flutter/shell/platform/windows/accessibility_plugin.h" | 
|  | #include "flutter/shell/platform/windows/compositor.h" | 
|  | #include "flutter/shell/platform/windows/cursor_handler.h" | 
|  | #include "flutter/shell/platform/windows/egl/manager.h" | 
|  | #include "flutter/shell/platform/windows/egl/proc_table.h" | 
|  | #include "flutter/shell/platform/windows/flutter_desktop_messenger.h" | 
|  | #include "flutter/shell/platform/windows/flutter_project_bundle.h" | 
|  | #include "flutter/shell/platform/windows/flutter_windows_texture_registrar.h" | 
|  | #include "flutter/shell/platform/windows/keyboard_handler_base.h" | 
|  | #include "flutter/shell/platform/windows/keyboard_key_embedder_handler.h" | 
|  | #include "flutter/shell/platform/windows/platform_handler.h" | 
|  | #include "flutter/shell/platform/windows/platform_view_plugin.h" | 
|  | #include "flutter/shell/platform/windows/public/flutter_windows.h" | 
|  | #include "flutter/shell/platform/windows/settings_plugin.h" | 
|  | #include "flutter/shell/platform/windows/task_runner.h" | 
|  | #include "flutter/shell/platform/windows/text_input_plugin.h" | 
|  | #include "flutter/shell/platform/windows/window_proc_delegate_manager.h" | 
|  | #include "flutter/shell/platform/windows/window_state.h" | 
|  | #include "flutter/shell/platform/windows/windows_lifecycle_manager.h" | 
|  | #include "flutter/shell/platform/windows/windows_proc_table.h" | 
|  | #include "third_party/rapidjson/include/rapidjson/document.h" | 
|  |  | 
|  | namespace flutter { | 
|  |  | 
|  | // The implicit view's ID. | 
|  | // | 
|  | // See: | 
|  | // https://api.flutter.dev/flutter/dart-ui/PlatformDispatcher/implicitView.html | 
|  | constexpr FlutterViewId kImplicitViewId = 0; | 
|  |  | 
|  | class FlutterWindowsView; | 
|  |  | 
|  | // Update the thread priority for the Windows engine. | 
|  | static void WindowsPlatformThreadPrioritySetter( | 
|  | FlutterThreadPriority priority) { | 
|  | // TODO(99502): Add support for tracing to the windows embedding so we can | 
|  | // mark thread priorities and success/failure. | 
|  | switch (priority) { | 
|  | case FlutterThreadPriority::kBackground: { | 
|  | SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL); | 
|  | break; | 
|  | } | 
|  | case FlutterThreadPriority::kDisplay: { | 
|  | SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); | 
|  | break; | 
|  | } | 
|  | case FlutterThreadPriority::kRaster: { | 
|  | SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); | 
|  | break; | 
|  | } | 
|  | case FlutterThreadPriority::kNormal: { | 
|  | // For normal or default priority we do not need to set the priority | 
|  | // class. | 
|  | break; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | // Manages state associated with the underlying FlutterEngine that isn't | 
|  | // related to its display. | 
|  | // | 
|  | // In most cases this will be associated with a FlutterView, but if not will | 
|  | // run in headless mode. | 
|  | class FlutterWindowsEngine { | 
|  | public: | 
|  | // Creates a new Flutter engine object configured to run |project|. | 
|  | FlutterWindowsEngine( | 
|  | const FlutterProjectBundle& project, | 
|  | std::shared_ptr<WindowsProcTable> windows_proc_table = nullptr); | 
|  |  | 
|  | virtual ~FlutterWindowsEngine(); | 
|  |  | 
|  | // Starts running the entrypoint function specifed in the project bundle. If | 
|  | // unspecified, defaults to main(). | 
|  | // | 
|  | // Returns false if the engine couldn't be started. | 
|  | bool Run(); | 
|  |  | 
|  | // Starts running the engine with the given entrypoint. If the empty string | 
|  | // is specified, defaults to the entrypoint function specified in the project | 
|  | // bundle, or main() if both are unspecified. | 
|  | // | 
|  | // Returns false if the engine couldn't be started or if conflicting, | 
|  | // non-default values are passed here and in the project bundle.. | 
|  | // | 
|  | // DEPRECATED: Prefer setting the entrypoint in the FlutterProjectBundle | 
|  | // passed to the constructor and calling the no-parameter overload. | 
|  | bool Run(std::string_view entrypoint); | 
|  |  | 
|  | // Returns true if the engine is currently running. | 
|  | virtual bool running() const { return engine_ != nullptr; } | 
|  |  | 
|  | // Stops the engine. This invalidates the pointer returned by engine(). | 
|  | // | 
|  | // Returns false if stopping the engine fails, or if it was not running. | 
|  | virtual bool Stop(); | 
|  |  | 
|  | // Create a view that can display this engine's content. | 
|  | // | 
|  | // Returns null on failure. | 
|  | std::unique_ptr<FlutterWindowsView> CreateView( | 
|  | std::unique_ptr<WindowBindingHandler> window); | 
|  |  | 
|  | // Remove a view. The engine will no longer render into it. | 
|  | virtual void RemoveView(FlutterViewId view_id); | 
|  |  | 
|  | // Get a view that displays this engine's content. | 
|  | // | 
|  | // Returns null if the view does not exist. | 
|  | FlutterWindowsView* view(FlutterViewId view_id) const; | 
|  |  | 
|  | // Returns the currently configured Plugin Registrar. | 
|  | FlutterDesktopPluginRegistrarRef GetRegistrar(); | 
|  |  | 
|  | // Registers |callback| to be called when the plugin registrar is destroyed. | 
|  | void AddPluginRegistrarDestructionCallback( | 
|  | FlutterDesktopOnPluginRegistrarDestroyed callback, | 
|  | FlutterDesktopPluginRegistrarRef registrar); | 
|  |  | 
|  | // Sets switches member to the given switches. | 
|  | void SetSwitches(const std::vector<std::string>& switches); | 
|  |  | 
|  | FlutterDesktopMessengerRef messenger() { return messenger_->ToRef(); } | 
|  |  | 
|  | IncomingMessageDispatcher* message_dispatcher() { | 
|  | return message_dispatcher_.get(); | 
|  | } | 
|  |  | 
|  | TaskRunner* task_runner() { return task_runner_.get(); } | 
|  |  | 
|  | BinaryMessenger* messenger_wrapper() { return messenger_wrapper_.get(); } | 
|  |  | 
|  | FlutterWindowsTextureRegistrar* texture_registrar() { | 
|  | return texture_registrar_.get(); | 
|  | } | 
|  |  | 
|  | // The EGL manager object. If this is nullptr, then we are | 
|  | // rendering using software instead of OpenGL. | 
|  | egl::Manager* egl_manager() const { return egl_manager_.get(); } | 
|  |  | 
|  | WindowProcDelegateManager* window_proc_delegate_manager() { | 
|  | return window_proc_delegate_manager_.get(); | 
|  | } | 
|  |  | 
|  | // Informs the engine that the window metrics have changed. | 
|  | void SendWindowMetricsEvent(const FlutterWindowMetricsEvent& event); | 
|  |  | 
|  | // Informs the engine of an incoming pointer event. | 
|  | void SendPointerEvent(const FlutterPointerEvent& event); | 
|  |  | 
|  | // Informs the engine of an incoming key event. | 
|  | void SendKeyEvent(const FlutterKeyEvent& event, | 
|  | FlutterKeyEventCallback callback, | 
|  | void* user_data); | 
|  |  | 
|  | KeyboardHandlerBase* keyboard_key_handler() { | 
|  | return keyboard_key_handler_.get(); | 
|  | } | 
|  | TextInputPlugin* text_input_plugin() { return text_input_plugin_.get(); } | 
|  |  | 
|  | // Sends the given message to the engine, calling |reply| with |user_data| | 
|  | // when a response is received from the engine if they are non-null. | 
|  | bool SendPlatformMessage(const char* channel, | 
|  | const uint8_t* message, | 
|  | const size_t message_size, | 
|  | const FlutterDesktopBinaryReply reply, | 
|  | void* user_data); | 
|  |  | 
|  | // Sends the given data as the response to an earlier platform message. | 
|  | void SendPlatformMessageResponse( | 
|  | const FlutterDesktopMessageResponseHandle* handle, | 
|  | const uint8_t* data, | 
|  | size_t data_length); | 
|  |  | 
|  | // Callback passed to Flutter engine for notifying window of platform | 
|  | // messages. | 
|  | void HandlePlatformMessage(const FlutterPlatformMessage*); | 
|  |  | 
|  | // Informs the engine that the system font list has changed. | 
|  | void ReloadSystemFonts(); | 
|  |  | 
|  | // Informs the engine that a new frame is needed to redraw the content. | 
|  | void ScheduleFrame(); | 
|  |  | 
|  | // Set the callback that is called when the next frame is drawn. | 
|  | void SetNextFrameCallback(fml::closure callback); | 
|  |  | 
|  | // Attempts to register the texture with the given |texture_id|. | 
|  | bool RegisterExternalTexture(int64_t texture_id); | 
|  |  | 
|  | // Attempts to unregister the texture with the given |texture_id|. | 
|  | bool UnregisterExternalTexture(int64_t texture_id); | 
|  |  | 
|  | // Notifies the engine about a new frame being available for the | 
|  | // given |texture_id|. | 
|  | bool MarkExternalTextureFrameAvailable(int64_t texture_id); | 
|  |  | 
|  | // Posts the given callback onto the raster thread. | 
|  | virtual bool PostRasterThreadTask(fml::closure callback) const; | 
|  |  | 
|  | // Invoke on the embedder's vsync callback to schedule a frame. | 
|  | void OnVsync(intptr_t baton); | 
|  |  | 
|  | // Dispatches a semantics action to the specified semantics node. | 
|  | bool DispatchSemanticsAction(uint64_t id, | 
|  | FlutterSemanticsAction action, | 
|  | fml::MallocMapping data); | 
|  |  | 
|  | // Informs the engine that the semantics enabled state has changed. | 
|  | void UpdateSemanticsEnabled(bool enabled); | 
|  |  | 
|  | // Returns true if the semantics tree is enabled. | 
|  | bool semantics_enabled() const { return semantics_enabled_; } | 
|  |  | 
|  | // Refresh accessibility features and send them to the engine. | 
|  | void UpdateAccessibilityFeatures(); | 
|  |  | 
|  | // Refresh high contrast accessibility mode and notify the engine. | 
|  | void UpdateHighContrastMode(); | 
|  |  | 
|  | // Returns true if the high contrast feature is enabled. | 
|  | bool high_contrast_enabled() const { return high_contrast_enabled_; } | 
|  |  | 
|  | // Register a root isolate create callback. | 
|  | // | 
|  | // The root isolate create callback is invoked at creation of the root Dart | 
|  | // isolate in the app. This may be used to be notified that execution of the | 
|  | // main Dart entrypoint is about to begin, and is used by test infrastructure | 
|  | // to register a native function resolver that can register and resolve | 
|  | // functions marked as native in the Dart code. | 
|  | // | 
|  | // This must be called before calling |Run|. | 
|  | void SetRootIsolateCreateCallback(const fml::closure& callback) { | 
|  | root_isolate_create_callback_ = callback; | 
|  | } | 
|  |  | 
|  | // Returns the executable name for this process or "Flutter" if unknown. | 
|  | std::string GetExecutableName() const; | 
|  |  | 
|  | // Called when the application quits in response to a quit request. | 
|  | void OnQuit(std::optional<HWND> hwnd, | 
|  | std::optional<WPARAM> wparam, | 
|  | std::optional<LPARAM> lparam, | 
|  | UINT exit_code); | 
|  |  | 
|  | // Called when a WM_CLOSE message is received. | 
|  | void RequestApplicationQuit(HWND hwnd, | 
|  | WPARAM wparam, | 
|  | LPARAM lparam, | 
|  | AppExitType exit_type); | 
|  |  | 
|  | // Called when a WM_DWMCOMPOSITIONCHANGED message is received. | 
|  | void OnDwmCompositionChanged(); | 
|  |  | 
|  | // Called when a Window receives an event that may alter the application | 
|  | // lifecycle state. | 
|  | void OnWindowStateEvent(HWND hwnd, WindowStateEvent event); | 
|  |  | 
|  | // Handle a message from a non-Flutter window in the same application. | 
|  | // Returns a result when the message is consumed and should not be processed | 
|  | // further. | 
|  | std::optional<LRESULT> ProcessExternalWindowMessage(HWND hwnd, | 
|  | UINT message, | 
|  | WPARAM wparam, | 
|  | LPARAM lparam); | 
|  |  | 
|  | WindowsLifecycleManager* lifecycle_manager() { | 
|  | return lifecycle_manager_.get(); | 
|  | } | 
|  |  | 
|  | std::shared_ptr<WindowsProcTable> windows_proc_table() { | 
|  | return windows_proc_table_; | 
|  | } | 
|  |  | 
|  | protected: | 
|  | // Creates the keyboard key handler. | 
|  | // | 
|  | // Exposing this method allows unit tests to override in order to | 
|  | // capture information. | 
|  | virtual std::unique_ptr<KeyboardHandlerBase> CreateKeyboardKeyHandler( | 
|  | BinaryMessenger* messenger, | 
|  | KeyboardKeyEmbedderHandler::GetKeyStateHandler get_key_state, | 
|  | KeyboardKeyEmbedderHandler::MapVirtualKeyToScanCode map_vk_to_scan); | 
|  |  | 
|  | // Creates the text input plugin. | 
|  | // | 
|  | // Exposing this method allows unit tests to override in order to | 
|  | // capture information. | 
|  | virtual std::unique_ptr<TextInputPlugin> CreateTextInputPlugin( | 
|  | BinaryMessenger* messenger); | 
|  |  | 
|  | // Invoked by the engine right before the engine is restarted. | 
|  | // | 
|  | // This should reset necessary states to as if the engine has just been | 
|  | // created. This is typically caused by a hot restart (Shift-R in CLI.) | 
|  | void OnPreEngineRestart(); | 
|  |  | 
|  | // Invoked by the engine when a listener is set or cleared on a platform | 
|  | // channel. | 
|  | virtual void OnChannelUpdate(std::string name, bool listening); | 
|  |  | 
|  | private: | 
|  | // Allows swapping out embedder_api_ calls in tests. | 
|  | friend class EngineModifier; | 
|  |  | 
|  | // Sends system locales to the engine. | 
|  | // | 
|  | // Should be called just after the engine is run, and after any relevant | 
|  | // system changes. | 
|  | void SendSystemLocales(); | 
|  |  | 
|  | // Sends the current lifecycle state to the framework. | 
|  | void SetLifecycleState(flutter::AppLifecycleState state); | 
|  |  | 
|  | // Create the keyboard & text input sub-systems. | 
|  | // | 
|  | // This requires that a view is attached to the engine. | 
|  | // Calling this method again resets the keyboard state. | 
|  | void InitializeKeyboard(); | 
|  |  | 
|  | // Send the currently enabled accessibility features to the engine. | 
|  | void SendAccessibilityFeatures(); | 
|  |  | 
|  | // Present content to a view. Returns true if the content was presented. | 
|  | // | 
|  | // This is invoked on the raster thread. | 
|  | bool Present(const FlutterPresentViewInfo* info); | 
|  |  | 
|  | // The handle to the embedder.h engine instance. | 
|  | FLUTTER_API_SYMBOL(FlutterEngine) engine_ = nullptr; | 
|  |  | 
|  | FlutterEngineProcTable embedder_api_ = {}; | 
|  |  | 
|  | std::unique_ptr<FlutterProjectBundle> project_; | 
|  |  | 
|  | // AOT data, if any. | 
|  | UniqueAotDataPtr aot_data_; | 
|  |  | 
|  | // The ID that the next view will have. | 
|  | FlutterViewId next_view_id_ = kImplicitViewId; | 
|  |  | 
|  | // The views displaying the content running in this engine, if any. | 
|  | // | 
|  | // This is read and mutated by the platform thread. This is read by the raster | 
|  | // thread to present content to a view. | 
|  | // | 
|  | // Reads to this object on non-platform threads must be protected | 
|  | // by acquiring a shared lock on |views_mutex_|. | 
|  | // | 
|  | // Writes to this object must only happen on the platform thread | 
|  | // and must be protected by acquiring an exclusive lock on |views_mutex_|. | 
|  | std::unordered_map<FlutterViewId, FlutterWindowsView*> views_; | 
|  |  | 
|  | // The mutex that protects the |views_| map. | 
|  | // | 
|  | // The raster thread acquires a shared lock to present to a view. | 
|  | // | 
|  | // The platform thread acquires a shared lock to access the view. | 
|  | // The platform thread acquires an exclusive lock before adding | 
|  | // a view to the engine or after removing a view from the engine. | 
|  | std::unique_ptr<fml::SharedMutex> views_mutex_; | 
|  |  | 
|  | // Task runner for tasks posted from the engine. | 
|  | std::unique_ptr<TaskRunner> task_runner_; | 
|  |  | 
|  | // The plugin messenger handle given to API clients. | 
|  | fml::RefPtr<flutter::FlutterDesktopMessenger> messenger_; | 
|  |  | 
|  | // A wrapper around messenger_ for interacting with client_wrapper-level APIs. | 
|  | std::unique_ptr<BinaryMessengerImpl> messenger_wrapper_; | 
|  |  | 
|  | // Message dispatch manager for messages from engine_. | 
|  | std::unique_ptr<IncomingMessageDispatcher> message_dispatcher_; | 
|  |  | 
|  | // The plugin registrar handle given to API clients. | 
|  | std::unique_ptr<FlutterDesktopPluginRegistrar> plugin_registrar_; | 
|  |  | 
|  | // The texture registrar. | 
|  | std::unique_ptr<FlutterWindowsTextureRegistrar> texture_registrar_; | 
|  |  | 
|  | // An object used for intializing ANGLE and creating / destroying render | 
|  | // surfaces. If nullptr, ANGLE failed to initialize and software rendering | 
|  | // should be used instead. | 
|  | std::unique_ptr<egl::Manager> egl_manager_; | 
|  |  | 
|  | // The compositor that creates backing stores for the engine to render into | 
|  | // and then presents them onto views. | 
|  | std::unique_ptr<Compositor> compositor_; | 
|  |  | 
|  | // The plugin registrar managing internal plugins. | 
|  | std::unique_ptr<PluginRegistrar> internal_plugin_registrar_; | 
|  |  | 
|  | // Handler for accessibility events. | 
|  | std::unique_ptr<AccessibilityPlugin> accessibility_plugin_; | 
|  |  | 
|  | // Handler for cursor events. | 
|  | std::unique_ptr<CursorHandler> cursor_handler_; | 
|  |  | 
|  | // Handler for the flutter/platform channel. | 
|  | std::unique_ptr<PlatformHandler> platform_handler_; | 
|  |  | 
|  | // Handlers for keyboard events from Windows. | 
|  | std::unique_ptr<KeyboardHandlerBase> keyboard_key_handler_; | 
|  |  | 
|  | // Handlers for text events from Windows. | 
|  | std::unique_ptr<TextInputPlugin> text_input_plugin_; | 
|  |  | 
|  | // The settings plugin. | 
|  | std::unique_ptr<SettingsPlugin> settings_plugin_; | 
|  |  | 
|  | // Callbacks to be called when the engine (and thus the plugin registrar) is | 
|  | // being destroyed. | 
|  | std::map<FlutterDesktopOnPluginRegistrarDestroyed, | 
|  | FlutterDesktopPluginRegistrarRef> | 
|  | plugin_registrar_destruction_callbacks_; | 
|  |  | 
|  | // The approximate time between vblank events. | 
|  | std::chrono::nanoseconds FrameInterval(); | 
|  |  | 
|  | // The start time used to align frames. | 
|  | std::chrono::nanoseconds start_time_ = std::chrono::nanoseconds::zero(); | 
|  |  | 
|  | // An override of the frame interval used by EngineModifier for testing. | 
|  | std::optional<std::chrono::nanoseconds> frame_interval_override_ = | 
|  | std::nullopt; | 
|  |  | 
|  | bool semantics_enabled_ = false; | 
|  |  | 
|  | bool high_contrast_enabled_ = false; | 
|  |  | 
|  | bool enable_impeller_ = false; | 
|  |  | 
|  | // The manager for WindowProc delegate registration and callbacks. | 
|  | std::unique_ptr<WindowProcDelegateManager> window_proc_delegate_manager_; | 
|  |  | 
|  | // The root isolate creation callback. | 
|  | fml::closure root_isolate_create_callback_; | 
|  |  | 
|  | // The on frame drawn callback. | 
|  | fml::closure next_frame_callback_; | 
|  |  | 
|  | // Handler for top level window messages. | 
|  | std::unique_ptr<WindowsLifecycleManager> lifecycle_manager_; | 
|  |  | 
|  | std::shared_ptr<WindowsProcTable> windows_proc_table_; | 
|  |  | 
|  | std::shared_ptr<egl::ProcTable> gl_; | 
|  |  | 
|  | std::unique_ptr<PlatformViewPlugin> platform_view_plugin_; | 
|  |  | 
|  | FML_DISALLOW_COPY_AND_ASSIGN(FlutterWindowsEngine); | 
|  | }; | 
|  |  | 
|  | }  // namespace flutter | 
|  |  | 
|  | #endif  // FLUTTER_SHELL_PLATFORM_WINDOWS_FLUTTER_WINDOWS_ENGINE_H_ |