| // 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_ |