// 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_COMMON_PLATFORM_VIEW_H_ #define FLUTTER_SHELL_COMMON_PLATFORM_VIEW_H_ #include #include #include "flutter/common/graphics/texture.h" #include "flutter/common/task_runners.h" #include "flutter/flow/embedded_views.h" #include "flutter/flow/surface.h" #include "flutter/fml/macros.h" #include "flutter/fml/mapping.h" #include "flutter/fml/memory/weak_ptr.h" #include "flutter/lib/ui/semantics/custom_accessibility_action.h" #include "flutter/lib/ui/semantics/semantics_node.h" #include "flutter/lib/ui/window/key_data_packet.h" #include "flutter/lib/ui/window/platform_message.h" #include "flutter/lib/ui/window/pointer_data_packet.h" #include "flutter/lib/ui/window/viewport_metrics.h" #include "flutter/shell/common/platform_message_handler.h" #include "flutter/shell/common/pointer_data_dispatcher.h" #include "flutter/shell/common/vsync_waiter.h" #include "third_party/skia/include/gpu/ganesh/GrDirectContext.h" namespace impeller { class Context; } // namespace impeller namespace flutter { //------------------------------------------------------------------------------ /// @brief Platform views are created by the shell on the platform task /// runner. Unless explicitly specified, all platform view methods /// are called on the platform task runner as well. Platform views /// are usually sub-classed on a per platform basis and the bulk of /// the window system integration happens using that subclass. Since /// most platform window toolkits are usually only safe to access on /// a single "main" thread, any interaction that requires access to /// the underlying platform's window toolkit is routed through the /// platform view associated with that shell. This involves /// operations like settings up and tearing down the render surface, /// platform messages, interacting with accessibility features on /// the platform, input events, etc. /// class PlatformView { public: using AddViewCallback = std::function; using RemoveViewCallback = std::function; //---------------------------------------------------------------------------- /// @brief Used to forward events from the platform view to interested /// subsystems. This forwarding is done by the shell which sets /// itself up as the delegate of the platform view. /// class Delegate { public: using AddViewCallback = PlatformView::AddViewCallback; using RemoveViewCallback = PlatformView::RemoveViewCallback; using KeyDataResponse = std::function; //-------------------------------------------------------------------------- /// @brief Notifies the delegate that the platform view was created /// with the given render surface. This surface is platform /// (iOS, Android) and client-rendering API (OpenGL, Software, /// Metal, Vulkan) specific. This is usually a sign to the /// rasterizer to set up and begin rendering to that surface. /// /// @param[in] surface The surface /// virtual void OnPlatformViewCreated(std::unique_ptr surface) = 0; //-------------------------------------------------------------------------- /// @brief Notifies the delegate that the platform view was destroyed. /// This is usually a sign to the rasterizer to suspend /// rendering a previously configured surface and collect any /// intermediate resources. /// virtual void OnPlatformViewDestroyed() = 0; //-------------------------------------------------------------------------- /// @brief Notifies the delegate that the platform needs to schedule a /// frame to regenerate the layer tree and redraw the surface. /// virtual void OnPlatformViewScheduleFrame() = 0; /// @brief Allocate resources for a new non-implicit view and inform /// Dart about the view, and on success, schedules a new frame. /// /// After the operation, |callback| should be invoked with whether /// the operation is successful. /// /// Adding |kFlutterImplicitViewId| or an existing view ID should /// result in failure. /// /// @param[in] view_id The view ID of the new view. /// @param[in] viewport_metrics The initial viewport metrics for the view. /// @param[in] callback The callback that's invoked once the shell /// has attempted to add the view. /// virtual void OnPlatformViewAddView(int64_t view_id, const ViewportMetrics& viewport_metrics, AddViewCallback callback) = 0; /// @brief Deallocate resources for a removed view and inform /// Dart about the removal. /// /// After the operation, |callback| should be invoked with whether /// the operation is successful. /// /// Removing |kFlutterImplicitViewId| or an non-existent view ID /// should result in failure. /// /// @param[in] view_id The view ID of the view to be removed. /// @param[in] callback The callback that's invoked once the shell has /// attempted to remove the view. /// virtual void OnPlatformViewRemoveView(int64_t view_id, RemoveViewCallback callback) = 0; //-------------------------------------------------------------------------- /// @brief Notifies the delegate that the specified callback needs to /// be invoked after the rasterizer is done rendering the next /// frame. This callback will be called on the render thread and /// it is caller responsibility to perform any re-threading as /// necessary. Due to the asynchronous nature of rendering in /// Flutter, embedders usually add a placeholder over the /// contents in which Flutter is going to render when Flutter is /// first initialized. This callback may be used as a signal to /// remove that placeholder. /// /// @attention The callback will be invoked on the render thread and not /// the calling thread. /// /// @param[in] closure The callback to execute on the next frame. /// virtual void OnPlatformViewSetNextFrameCallback( const fml::closure& closure) = 0; //-------------------------------------------------------------------------- /// @brief Notifies the delegate the viewport metrics of a view have /// been updated. The rasterizer will need to be reconfigured to /// render the frame in the updated viewport metrics. /// /// @param[in] view_id The ID for the view that `metrics` describes. /// @param[in] metrics The updated viewport metrics. /// virtual void OnPlatformViewSetViewportMetrics( int64_t view_id, const ViewportMetrics& metrics) = 0; //-------------------------------------------------------------------------- /// @brief Notifies the delegate that the platform has dispatched a /// platform message from the embedder to the Flutter /// application. This message must be forwarded to the running /// isolate hosted by the engine on the UI thread. /// /// @param[in] message The platform message to dispatch to the running /// root isolate. /// virtual void OnPlatformViewDispatchPlatformMessage( std::unique_ptr message) = 0; //-------------------------------------------------------------------------- /// @brief Notifies the delegate that the platform view has encountered /// a pointer event. This pointer event needs to be forwarded to /// the running root isolate hosted by the engine on the UI /// thread. /// /// @param[in] packet The pointer data packet containing multiple pointer /// events. /// virtual void OnPlatformViewDispatchPointerDataPacket( std::unique_ptr packet) = 0; //-------------------------------------------------------------------------- /// @brief Notifies the delegate that the platform view has encountered /// an accessibility related action on the specified node. This /// event must be forwarded to the running root isolate hosted /// by the engine on the UI thread. /// /// @param[in] node_id The identifier of the accessibility node. /// @param[in] action The accessibility related action performed on the /// node of the specified ID. /// @param[in] args An optional list of argument that apply to the /// specified action. /// virtual void OnPlatformViewDispatchSemanticsAction( int32_t node_id, SemanticsAction action, fml::MallocMapping args) = 0; //-------------------------------------------------------------------------- /// @brief Notifies the delegate that the embedder has expressed an /// opinion about whether the accessibility tree needs to be /// enabled or disabled. This information needs to be forwarded /// to the root isolate running on the UI thread. /// /// @param[in] enabled Whether the accessibility tree is enabled or /// disabled. /// virtual void OnPlatformViewSetSemanticsEnabled(bool enabled) = 0; //-------------------------------------------------------------------------- /// @brief Notifies the delegate that the embedder has expressed an /// opinion about the features to enable in the accessibility /// tree. /// /// The engine does not care about the accessibility feature /// flags as all it does is forward this information from the /// embedder to the framework. However, curious readers may /// refer to `AccessibilityFeatures` in `window.dart` for /// currently supported accessibility feature flags. /// /// @param[in] flags The features to enable in the accessibility tree. /// virtual void OnPlatformViewSetAccessibilityFeatures(int32_t flags) = 0; //-------------------------------------------------------------------------- /// @brief Notifies the delegate that the embedder has specified a /// texture that it want the rasterizer to composite within the /// Flutter layer tree. All textures must have a unique /// identifier. When the rasterizer encounters an external /// texture within its hierarchy, it gives the embedder a chance /// to update that texture on the raster thread before it /// composites the same on-screen. /// /// @param[in] texture The texture that is being updated by the embedder /// but composited by Flutter in its own hierarchy. /// virtual void OnPlatformViewRegisterTexture( std::shared_ptr texture) = 0; //-------------------------------------------------------------------------- /// @brief Notifies the delegate that the embedder will no longer /// attempt to composite the specified texture within the layer /// tree. This allows the rasterizer to collect associated /// resources. /// /// @param[in] texture_id The identifier of the texture to unregister. If /// the texture has not been previously registered, /// this call does nothing. /// virtual void OnPlatformViewUnregisterTexture(int64_t texture_id) = 0; //-------------------------------------------------------------------------- /// @brief Notifies the delegate that the embedder has updated the /// contents of the texture with the specified identifier. /// Typically, Flutter will only render a frame if there is an /// updated layer tree. However, in cases where the layer tree /// is static but one of the externally composited textures has /// been updated by the embedder, the embedder needs to notify /// the rasterizer to render a new frame. In such cases, the /// existing layer tree may be reused with the frame composited /// with all updated external textures. /// /// @param[in] texture_id The identifier of the texture that has been /// updated. /// virtual void OnPlatformViewMarkTextureFrameAvailable( int64_t texture_id) = 0; //-------------------------------------------------------------------------- /// @brief Loads the dart shared library into the dart VM. When the /// dart library is loaded successfully, the dart future /// returned by the originating loadLibrary() call completes. /// /// The Dart compiler may generate separate shared libraries /// files called 'loading units' when libraries are imported /// as deferred. Each of these shared libraries are identified /// by a unique loading unit id. Callers should open and resolve /// a SymbolMapping from the shared library. The Mappings should /// be moved into this method, as ownership will be assumed by /// the dart root isolate after successful loading and released /// after shutdown of the root isolate. The loading unit may not /// be used after isolate shutdown. If loading fails, the /// mappings will be released. /// /// This method is paired with a RequestDartDeferredLibrary /// invocation that provides the embedder with the loading unit /// id of the deferred library to load. /// /// /// @param[in] loading_unit_id The unique id of the deferred library's /// loading unit. /// /// @param[in] snapshot_data Dart snapshot data of the loading unit's /// shared library. /// /// @param[in] snapshot_data Dart snapshot instructions of the loading /// unit's shared library. /// virtual void LoadDartDeferredLibrary( intptr_t loading_unit_id, std::unique_ptr snapshot_data, std::unique_ptr snapshot_instructions) = 0; //-------------------------------------------------------------------------- /// @brief Indicates to the dart VM that the request to load a deferred /// library with the specified loading unit id has failed. /// /// The dart future returned by the initiating loadLibrary() /// call will complete with an error. /// /// @param[in] loading_unit_id The unique id of the deferred library's /// loading unit, as passed in by /// RequestDartDeferredLibrary. /// /// @param[in] error_message The error message that will appear in the /// dart Future. /// /// @param[in] transient A transient error is a failure due to /// temporary conditions such as no network. /// Transient errors allow the dart VM to /// re-request the same deferred library and /// loading_unit_id again. Non-transient /// errors are permanent and attempts to /// re-request the library will instantly /// complete with an error. virtual void LoadDartDeferredLibraryError(intptr_t loading_unit_id, const std::string error_message, bool transient) = 0; //-------------------------------------------------------------------------- /// @brief Replaces the asset resolver handled by the engine's /// AssetManager of the specified `type` with /// `updated_asset_resolver`. The matching AssetResolver is /// removed and replaced with `updated_asset_resolvers`. /// /// AssetResolvers should be updated when the existing resolver /// becomes obsolete and a newer one becomes available that /// provides updated access to the same type of assets as the /// existing one. This update process is meant to be performed /// at runtime. /// /// If a null resolver is provided, nothing will be done. If no /// matching resolver is found, the provided resolver will be /// added to the end of the AssetManager resolvers queue. The /// replacement only occurs with the first matching resolver. /// Any additional matching resolvers are untouched. /// /// @param[in] updated_asset_resolver The asset resolver to replace the /// resolver of matching type with. /// /// @param[in] type The type of AssetResolver to update. Only resolvers of /// the specified type will be replaced by the updated /// resolver. /// virtual void UpdateAssetResolverByType( std::unique_ptr updated_asset_resolver, AssetResolver::AssetResolverType type) = 0; //-------------------------------------------------------------------------- /// @brief Called by the platform view on the platform thread to get /// the settings object associated with the platform view /// instance. /// /// @return The settings. /// virtual const Settings& OnPlatformViewGetSettings() const = 0; }; //---------------------------------------------------------------------------- /// @brief Creates a platform view with the specified delegate and task /// runner. The base class by itself does not do much but is /// suitable for use in test environments where full platform /// integration may not be necessary. The platform view may only /// be created, accessed and destroyed on the platform task /// runner. /// /// @param delegate The delegate. This is typically the shell. /// @param[in] task_runners The task runners used by this platform view. /// explicit PlatformView(Delegate& delegate, const TaskRunners& task_runners); //---------------------------------------------------------------------------- /// @brief Destroys the platform view. The platform view is owned by the /// shell and will be destroyed by the same on the platform tasks /// runner. /// virtual ~PlatformView(); //---------------------------------------------------------------------------- /// @brief Invoked by the shell to obtain a platform specific vsync /// waiter. It is optional for platforms to override this method /// and provide a custom vsync waiter because a timer based /// fall-back waiter is used by default. However, it is highly /// recommended that platform provide their own Vsync waiter as /// the timer based fall-back will not render frames aligned with /// vsync boundaries. /// /// @attention If a timer based fall-back is used, a warning is logged to the /// console. In case this method is overridden in a subclass, it /// must return a valid vsync waiter. Returning null will lead to /// internal errors. If a valid vsync waiter cannot be returned, /// subclasses should just call the based class method instead. /// /// @return A vsync waiter. If is an internal error to return a null /// waiter. /// virtual std::unique_ptr CreateVSyncWaiter(); //---------------------------------------------------------------------------- /// @brief Used by embedders to dispatch a platform message to a /// running root isolate hosted by the engine. If an isolate is /// not running, the message is dropped. If there is no one on the /// other side listening on the channel, the message is dropped. /// When a platform message is dropped, any response handles /// associated with that message will be dropped as well. All /// users of platform messages must assume that message may not be /// delivered and/or their response handles may not be invoked. /// Platform messages are not buffered. /// /// For embedders that wish to respond to platform message /// directed from the framework to the embedder, the /// `HandlePlatformMessage` method may be overridden. /// /// @see HandlePlatformMessage() /// /// @param[in] message The platform message to deliver to the root isolate. /// void DispatchPlatformMessage(std::unique_ptr message); //---------------------------------------------------------------------------- /// @brief Overridden by embedders to perform actions in response to /// platform messages sent from the framework to the embedder. /// Default implementation of this method simply returns an empty /// response. /// /// Embedders that wish to send platform messages to the framework /// may use the `DispatchPlatformMessage` method. This method is /// for messages that go the other way. /// /// @see DispatchPlatformMessage() /// /// @param[in] message The message /// virtual void HandlePlatformMessage(std::unique_ptr message); //---------------------------------------------------------------------------- /// @brief Used by embedders to dispatch an accessibility action to a /// running isolate hosted by the engine. /// /// @param[in] node_id The identifier of the accessibility node on which to /// perform the action. /// @param[in] action The action /// @param[in] args The arguments /// void DispatchSemanticsAction(int32_t node_id, SemanticsAction action, fml::MallocMapping args); //---------------------------------------------------------------------------- /// @brief Used by embedder to notify the running isolate hosted by the /// engine on the UI thread that the accessibility tree needs to /// be generated. /// /// @attention Subclasses may choose to override this method to perform /// platform specific functions. However, they must call the base /// class method at some point in their implementation. /// /// @param[in] enabled Whether the accessibility tree needs to be generated. /// virtual void SetSemanticsEnabled(bool enabled); //---------------------------------------------------------------------------- /// @brief Used by the embedder to specify the features to enable in the /// accessibility tree generated by the isolate. This information /// is forwarded to the root isolate hosted by the engine on the /// UI thread. /// /// The engine does not care about the accessibility feature flags /// as all it does is forward this information from the embedder /// to the framework. However, curious readers may refer to /// `AccessibilityFeatures` in `window.dart` for currently /// supported accessibility feature flags. /// /// @attention Subclasses may choose to override this method to perform /// platform specific functions. However, they must call the base /// class method at some point in their implementation. /// /// @param[in] flags The features to enable in the accessibility tree. /// virtual void SetAccessibilityFeatures(int32_t flags); //---------------------------------------------------------------------------- /// @brief Used by the framework to tell the embedder to apply the /// specified semantics node updates. The default implementation /// of this method does nothing. /// /// @see SemanticsNode, SemticsNodeUpdates, /// CustomAccessibilityActionUpdates /// /// @param[in] updates A map with the stable semantics node identifier as /// key and the node properties as the value. /// @param[in] actions A map with the stable semantics node identifier as /// key and the custom node action as the value. /// virtual void UpdateSemantics(SemanticsNodeUpdates updates, CustomAccessibilityActionUpdates actions); //---------------------------------------------------------------------------- /// @brief Used by the framework to tell the embedder that it has /// registered a listener on a given channel. /// /// @param[in] name The name of the channel on which the listener has /// set or cleared a listener. /// @param[in] listening True if a listener has been set, false if it has /// been cleared. /// virtual void SendChannelUpdate(const std::string& name, bool listening); //---------------------------------------------------------------------------- /// @brief Used by embedders to specify the updated viewport metrics for /// a view. In response to this call, on the raster thread, the /// rasterizer may need to be reconfigured to the updated viewport /// dimensions. On the UI thread, the framework may need to start /// generating a new frame for the updated viewport metrics as /// well. /// /// @param[in] view_id The ID for the view that `metrics` describes. /// @param[in] metrics The updated viewport metrics. /// void SetViewportMetrics(int64_t view_id, const ViewportMetrics& metrics); //---------------------------------------------------------------------------- /// @brief Used by embedders to notify the shell that a platform view /// has been created. This notification is used to create a /// rendering surface and pick the client rendering API to use to /// render into this surface. No frames will be scheduled or /// rendered before this call. The surface must remain valid till /// the corresponding call to NotifyDestroyed. /// void NotifyCreated(); //---------------------------------------------------------------------------- /// @brief Used by embedders to notify the shell that the platform view /// has been destroyed. This notification used to collect the /// rendering surface and all associated resources. Frame /// scheduling is also suspended. /// /// @attention Subclasses may choose to override this method to perform /// platform specific functions. However, they must call the base /// class method at some point in their implementation. /// virtual void NotifyDestroyed(); //---------------------------------------------------------------------------- /// @brief Used by embedders to schedule a frame. In response to this /// call, the framework may need to start generating a new frame. /// void ScheduleFrame(); /// @brief Used by embedders to notify the shell of a new non-implicit view. /// /// This method notifies the shell to allocate resources and inform /// Dart about the view, and on success, schedules a new frame. /// Finally, it invokes |callback| with whether the operation is /// successful. /// /// This operation is asynchronous; avoid using the view until /// |callback| returns true. Callers should prepare resources for the /// view (if any) in advance but be ready to clean up on failure. /// /// The callback is called on a different thread. /// /// Do not use for implicit views, which are added internally during /// shell initialization. Adding |kFlutterImplicitViewId| or an /// existing view ID will fail, indicated by |callback| returning /// false. /// /// @param[in] view_id The view ID of the new view. /// @param[in] viewport_metrics The initial viewport metrics for the view. /// @param[in] callback The callback that's invoked once the shell /// has attempted to add the view. /// void AddView(int64_t view_id, const ViewportMetrics& viewport_metrics, AddViewCallback callback); /// @brief Used by embedders to notify the shell of a removed non-implicit /// view. /// /// This method notifies the shell to deallocate resources and inform /// Dart about the removal. Finally, it invokes |callback| with /// whether the operation is successful. /// /// This operation is asynchronous. The embedder should not deallocate /// resources until the |callback| is invoked. /// /// The callback is called on a different thread. /// /// Do not use for implicit views, which are never removed throughout /// the lifetime of the app. /// Removing |kFlutterImplicitViewId| or an /// non-existent view ID will fail, indicated by |callback| returning /// false. /// /// @param[in] view_id The view ID of the view to be removed. /// @param[in] callback The callback that's invoked once the shell has /// attempted to remove the view. /// void RemoveView(int64_t view_id, RemoveViewCallback callback); //---------------------------------------------------------------------------- /// @brief Used by the shell to obtain a Skia GPU context that is capable /// of operating on the IO thread. The context must be in the same /// share-group as the Skia GPU context used on the render thread. /// This context will always be used on the IO thread. Because it /// is in the same share-group as the separate render thread /// context, any GPU resources uploaded in this context will be /// visible to the render thread context (synchronization of GPU /// resources is managed by Skia). /// /// If such context cannot be created on the IO thread, callers /// may return `nullptr`. This will mean that all texture uploads /// will be queued onto the render thread which will cause /// performance issues. When this context is `nullptr`, an error /// is logged to the console. It is highly recommended that all /// platforms provide a resource context. /// /// @attention Unlike all other methods on the platform view, this will be /// called on IO task runner. /// /// @return The Skia GPU context that is in the same share-group as the /// main render thread GPU context. May be `nullptr` in case such /// a context cannot be created. /// virtual sk_sp CreateResourceContext() const; virtual std::shared_ptr GetImpellerContext() const; //---------------------------------------------------------------------------- /// @brief Used by the shell to notify the embedder that the resource /// context previously obtained via a call to /// `CreateResourceContext()` is being collected. The embedder /// is free to collect an platform specific resources /// associated with this context. /// /// @attention Unlike all other methods on the platform view, this will be /// called on IO task runner. /// virtual void ReleaseResourceContext() const; //-------------------------------------------------------------------------- /// @brief Returns a platform-specific PointerDataDispatcherMaker so the /// `Engine` can construct the PointerDataPacketDispatcher based /// on platforms. virtual PointerDataDispatcherMaker GetDispatcherMaker(); //---------------------------------------------------------------------------- /// @brief Returns a weak pointer to the platform view. Since the /// platform view may only be created, accessed and destroyed /// on the platform thread, any access to the platform view /// from a non-platform task runner needs a weak pointer to /// the platform view along with a reference to the platform /// task runner. A task must be posted to the platform task /// runner with the weak pointer captured in the same. The /// platform view method may only be called in the posted task /// once the weak pointer validity has been checked. This /// method is used by callers to obtain that weak pointer. /// /// @return The weak pointer to the platform view. /// fml::WeakPtr GetWeakPtr() const; //---------------------------------------------------------------------------- /// @brief Gives embedders a chance to react to a "cold restart" of the /// running isolate. The default implementation of this method /// does nothing. /// /// While a "hot restart" patches a running isolate, a "cold /// restart" restarts the root isolate in a running shell. /// virtual void OnPreEngineRestart() const; //---------------------------------------------------------------------------- /// @brief Sets a callback that gets executed when the rasterizer renders /// the next frame. Due to the asynchronous nature of /// rendering in Flutter, embedders usually add a placeholder /// over the contents in which Flutter is going to render when /// Flutter is first initialized. This callback may be used as /// a signal to remove that placeholder. The callback is /// executed on the render task runner and not the platform /// task runner. It is the embedder's responsibility to /// re-thread as necessary. /// /// @attention The callback is executed on the render task runner and not the /// platform task runner. Embedders must re-thread as necessary. /// /// @param[in] closure The callback to execute on the render thread when the /// next frame gets rendered. /// void SetNextFrameCallback(const fml::closure& closure); //---------------------------------------------------------------------------- /// @brief Dispatches pointer events from the embedder to the /// framework. Each pointer data packet may contain multiple /// pointer input events. Each call to this method wakes up /// the UI thread. /// /// @param[in] packet The pointer data packet to dispatch to the framework. /// void DispatchPointerDataPacket(std::unique_ptr packet); //-------------------------------------------------------------------------- /// @brief Used by the embedder to specify a texture that it wants the /// rasterizer to composite within the Flutter layer tree. All /// textures must have a unique identifier. When the /// rasterizer encounters an external texture within its /// hierarchy, it gives the embedder a chance to update that /// texture on the raster thread before it composites the same /// on-screen. /// /// @attention This method must only be called once per texture. When the /// texture is updated, calling `MarkTextureFrameAvailable` /// with the specified texture identifier is sufficient to /// make Flutter re-render the frame with the updated texture /// composited in-line. /// /// @see UnregisterTexture, MarkTextureFrameAvailable /// /// @param[in] texture The texture that is being updated by the embedder /// but composited by Flutter in its own hierarchy. /// void RegisterTexture(std::shared_ptr texture); //-------------------------------------------------------------------------- /// @brief Used by the embedder to notify the rasterizer that it will /// no longer attempt to composite the specified texture within /// the layer tree. This allows the rasterizer to collect /// associated resources. /// /// @attention This call must only be called once per texture identifier. /// /// @see RegisterTexture, MarkTextureFrameAvailable /// /// @param[in] texture_id The identifier of the texture to unregister. If /// the texture has not been previously registered, /// this call does nothing. /// void UnregisterTexture(int64_t texture_id); //-------------------------------------------------------------------------- /// @brief Used by the embedder to notify the rasterizer that the context /// of the previously registered texture have been updated. /// Typically, Flutter will only render a frame if there is an /// updated layer tree. However, in cases where the layer tree /// is static but one of the externally composited textures /// has been updated by the embedder, the embedder needs to /// notify the rasterizer to render a new frame. In such /// cases, the existing layer tree may be reused with the /// frame re-composited with all updated external textures. /// Unlike the calls to register and unregister the texture, /// this call must be made each time a new texture frame is /// available. /// /// @see RegisterTexture, UnregisterTexture /// /// @param[in] texture_id The identifier of the texture that has been /// updated. /// void MarkTextureFrameAvailable(int64_t texture_id); //-------------------------------------------------------------------------- /// @brief Directly invokes platform-specific APIs to compute the /// locale the platform would have natively resolved to. /// /// @param[in] supported_locale_data The vector of strings that represents /// the locales supported by the app. /// Each locale consists of three /// strings: languageCode, countryCode, /// and scriptCode in that order. /// /// @return A vector of 3 strings languageCode, countryCode, and /// scriptCode that represents the locale selected by the /// platform. Empty strings mean the value was unassigned. Empty /// vector represents a null locale. /// virtual std::unique_ptr> ComputePlatformResolvedLocales( const std::vector& supported_locale_data); virtual std::shared_ptr CreateExternalViewEmbedder(); //-------------------------------------------------------------------------- /// @brief Invoked when the dart VM requests that a deferred library /// be loaded. Notifies the engine that the deferred library /// identified by the specified loading unit id should be /// downloaded and loaded into the Dart VM via /// `LoadDartDeferredLibrary` /// /// Upon encountering errors or otherwise failing to load a /// loading unit with the specified id, the failure should be /// directly reported to dart by calling /// `LoadDartDeferredLibraryFailure` to ensure the waiting dart /// future completes with an error. /// /// @param[in] loading_unit_id The unique id of the deferred library's /// loading unit. This id is to be passed /// back into LoadDartDeferredLibrary /// in order to identify which deferred /// library to load. /// virtual void RequestDartDeferredLibrary(intptr_t loading_unit_id); //-------------------------------------------------------------------------- /// @brief Loads the Dart shared library into the Dart VM. When the /// Dart library is loaded successfully, the Dart future /// returned by the originating loadLibrary() call completes. /// /// The Dart compiler may generate separate shared libraries /// files called 'loading units' when libraries are imported /// as deferred. Each of these shared libraries are identified /// by a unique loading unit id. Callers should open and resolve /// a SymbolMapping from the shared library. The Mappings should /// be moved into this method, as ownership will be assumed by the /// dart isolate after successful loading and released after /// shutdown of the dart isolate. If loading fails, the mappings /// will naturally go out of scope. /// /// This method is paired with a RequestDartDeferredLibrary /// invocation that provides the embedder with the loading unit id /// of the deferred library to load. /// /// /// @param[in] loading_unit_id The unique id of the deferred library's /// loading unit, as passed in by /// RequestDartDeferredLibrary. /// /// @param[in] snapshot_data Dart snapshot data of the loading unit's /// shared library. /// /// @param[in] snapshot_data Dart snapshot instructions of the loading /// unit's shared library. /// virtual void LoadDartDeferredLibrary( intptr_t loading_unit_id, std::unique_ptr snapshot_data, std::unique_ptr snapshot_instructions); //-------------------------------------------------------------------------- /// @brief Indicates to the dart VM that the request to load a deferred /// library with the specified loading unit id has failed. /// /// The dart future returned by the initiating loadLibrary() call /// will complete with an error. /// /// @param[in] loading_unit_id The unique id of the deferred library's /// loading unit, as passed in by /// RequestDartDeferredLibrary. /// /// @param[in] error_message The error message that will appear in the /// dart Future. /// /// @param[in] transient A transient error is a failure due to /// temporary conditions such as no network. /// Transient errors allow the dart VM to /// re-request the same deferred library and /// loading_unit_id again. Non-transient /// errors are permanent and attempts to /// re-request the library will instantly /// complete with an error. /// virtual void LoadDartDeferredLibraryError(intptr_t loading_unit_id, const std::string error_message, bool transient); //-------------------------------------------------------------------------- /// @brief Replaces the asset resolver handled by the engine's /// AssetManager of the specified `type` with /// `updated_asset_resolver`. The matching AssetResolver is /// removed and replaced with `updated_asset_resolvers`. /// /// AssetResolvers should be updated when the existing resolver /// becomes obsolete and a newer one becomes available that /// provides updated access to the same type of assets as the /// existing one. This update process is meant to be performed /// at runtime. /// /// If a null resolver is provided, nothing will be done. If no /// matching resolver is found, the provided resolver will be /// added to the end of the AssetManager resolvers queue. The /// replacement only occurs with the first matching resolver. /// Any additional matching resolvers are untouched. /// /// @param[in] updated_asset_resolver The asset resolver to replace the /// resolver of matching type with. /// /// @param[in] type The type of AssetResolver to update. Only resolvers of /// the specified type will be replaced by the updated /// resolver. /// virtual void UpdateAssetResolverByType( std::unique_ptr updated_asset_resolver, AssetResolver::AssetResolverType type); //-------------------------------------------------------------------------- /// @brief Creates an object that produces surfaces suitable for raster /// snapshotting. The rasterizer will request this surface if no /// on screen surface is currently available when an application /// requests a snapshot, e.g. if `Scene.toImage` or /// `Picture.toImage` are called while the application is in the /// background. /// /// Not all backends support this kind of surface usage, and the /// default implementation returns nullptr. Platforms should /// override this if they can support GPU operations in the /// background and support GPU resource context usage. /// virtual std::unique_ptr CreateSnapshotSurfaceProducer(); //-------------------------------------------------------------------------- /// @brief Specifies a delegate that will receive PlatformMessages from /// Flutter to the host platform. /// /// @details If this returns `null` that means PlatformMessages should be sent /// to the PlatformView. That is to protect legacy behavior, any embedder /// that wants to support executing Platform Channel handlers on background /// threads should be returning a thread-safe PlatformMessageHandler instead. virtual std::shared_ptr GetPlatformMessageHandler() const; //---------------------------------------------------------------------------- /// @brief Get the settings for this platform view instance. /// /// @return The settings. /// const Settings& GetSettings() const; //-------------------------------------------------------------------------- /// @brief Synchronously invokes platform-specific APIs to apply the /// system text scaling on the given unscaled font size. /// /// Platforms that support this feature (currently it's only /// implemented for Android SDK level 34+) will send a valid /// configuration_id to potential callers, before this method can /// be called. /// /// @param[in] unscaled_font_size The unscaled font size specified by the /// app developer. The value is in logical /// pixels, and is guaranteed to be finite and /// non-negative. /// @param[in] configuration_id The unique id of the configuration to use /// for computing the scaled font size. /// /// @return The scaled font size in logical pixels, or -1 if the given /// configuration_id did not match a valid configuration. /// virtual double GetScaledFontSize(double unscaled_font_size, int configuration_id) const; protected: // This is the only method called on the raster task runner. virtual std::unique_ptr CreateRenderingSurface(); PlatformView::Delegate& delegate_; const TaskRunners task_runners_; fml::WeakPtrFactory weak_factory_; // Must be the last member. private: FML_DISALLOW_COPY_AND_ASSIGN(PlatformView); }; } // namespace flutter #endif // FLUTTER_SHELL_COMMON_PLATFORM_VIEW_H_