From d9dfd1b7c6de5cabf3ca4d7cd5b4778102611c94 Mon Sep 17 00:00:00 2001 From: JunsuChoi Date: Tue, 11 Jun 2024 13:26:47 +0900 Subject: [PATCH] [engine] Sync Flutter 3.22.0 source code (#67) --- .../platform/common/accessibility_bridge.cc | 27 ++-- .../platform/common/accessibility_bridge.h | 10 -- .../include/flutter/basic_message_channel.h | 6 +- .../include/flutter/event_channel.h | 2 +- .../include/flutter/method_result_functions.h | 3 +- .../include/flutter/plugin_registrar.h | 2 +- .../include/flutter/texture_registrar.h | 5 +- .../common/incoming_message_dispatcher.h | 6 +- flutter/shell/platform/common/path_utils.h | 6 +- .../platform/common/platform_provided_menu.h | 6 +- .../common/public/flutter_messenger.h | 2 + .../shell/platform/common/text_input_model.cc | 15 ++- .../shell/platform/common/text_input_model.h | 15 ++- flutter/shell/platform/embedder/embedder.h | 116 +++++++++++++++++- 14 files changed, 167 insertions(+), 54 deletions(-) diff --git a/flutter/shell/platform/common/accessibility_bridge.cc b/flutter/shell/platform/common/accessibility_bridge.cc index f45481f..9a6e020 100644 --- a/flutter/shell/platform/common/accessibility_bridge.cc +++ b/flutter/shell/platform/common/accessibility_bridge.cc @@ -91,7 +91,7 @@ void AccessibilityBridge::CommitUpdates() { } for (size_t i = results.size(); i > 0; i--) { - for (SemanticsNode node : results[i - 1]) { + for (const SemanticsNode& node : results[i - 1]) { ConvertFlutterUpdate(node, update); } } @@ -149,18 +149,6 @@ AccessibilityBridge::GetPendingEvents() const { return result; } -void AccessibilityBridge::RecreateNodeDelegates() { - for (const auto& [node_id, old_platform_node_delegate] : id_wrapper_map_) { - std::shared_ptr platform_node_delegate = - CreateFlutterPlatformNodeDelegate(); - platform_node_delegate->Init( - std::static_pointer_cast( - shared_from_this()), - old_platform_node_delegate->GetAXNode()); - id_wrapper_map_[node_id] = platform_node_delegate; - } -} - void AccessibilityBridge::OnNodeWillBeDeleted(ui::AXTree* tree, ui::AXNode* node) {} @@ -215,7 +203,7 @@ std::optional AccessibilityBridge::CreateRemoveReparentedNodesUpdate() { std::unordered_map updates; - for (auto node_update : pending_semantics_node_updates_) { + for (const auto& node_update : pending_semantics_node_updates_) { for (int32_t child_id : node_update.second.children_in_traversal_order) { // Skip nodes that don't exist or have a parent in the current tree. ui::AXNode* child = tree_->GetFromId(child_id); @@ -345,7 +333,7 @@ void AccessibilityBridge::SetRoleFromFlutterUpdate(ui::AXNodeData& node_data, return; } if (flags & kFlutterSemanticsFlagHasToggledState) { - node_data.role = ax::mojom::Role::kToggleButton; + node_data.role = ax::mojom::Role::kSwitch; return; } if (flags & kFlutterSemanticsFlagIsSlider) { @@ -365,6 +353,13 @@ void AccessibilityBridge::SetStateFromFlutterUpdate(ui::AXNodeData& node_data, const SemanticsNode& node) { FlutterSemanticsFlag flags = node.flags; FlutterSemanticsAction actions = node.actions; + if (flags & FlutterSemanticsFlag::kFlutterSemanticsFlagHasExpandedState && + flags & FlutterSemanticsFlag::kFlutterSemanticsFlagIsExpanded) { + node_data.AddState(ax::mojom::State::kExpanded); + } else if (flags & + FlutterSemanticsFlag::kFlutterSemanticsFlagHasExpandedState) { + node_data.AddState(ax::mojom::State::kCollapsed); + } if (flags & FlutterSemanticsFlag::kFlutterSemanticsFlagIsTextField && (flags & FlutterSemanticsFlag::kFlutterSemanticsFlagIsReadOnly) == 0) { node_data.AddState(ax::mojom::State::kEditable); @@ -482,7 +477,7 @@ void AccessibilityBridge::SetIntAttributesFromFlutterUpdate( : flags & FlutterSemanticsFlag::kFlutterSemanticsFlagIsChecked ? ax::mojom::CheckedState::kTrue : ax::mojom::CheckedState::kFalse)); - } else if (node_data.role == ax::mojom::Role::kToggleButton) { + } else if (node_data.role == ax::mojom::Role::kSwitch) { node_data.AddIntAttribute( ax::mojom::IntAttribute::kCheckedState, static_cast( diff --git a/flutter/shell/platform/common/accessibility_bridge.h b/flutter/shell/platform/common/accessibility_bridge.h index 06a15e4..7e66980 100644 --- a/flutter/shell/platform/common/accessibility_bridge.h +++ b/flutter/shell/platform/common/accessibility_bridge.h @@ -157,16 +157,6 @@ class AccessibilityBridge virtual std::shared_ptr CreateFlutterPlatformNodeDelegate() = 0; - //------------------------------------------------------------------------------ - /// @brief Recreate all FlutterPlatformNodeDelegates. - /// - /// This can be useful for subclasses when updating some - /// properties that are used by node delegates, such as views. - /// Each node is recreated using - /// CreateFlutterPlatformNodeDelegate, then initialized using - /// AXNodes from their corresponding old one. - void RecreateNodeDelegates(); - private: // See FlutterSemanticsNode in embedder.h typedef struct { diff --git a/flutter/shell/platform/common/client_wrapper/include/flutter/basic_message_channel.h b/flutter/shell/platform/common/client_wrapper/include/flutter/basic_message_channel.h index 5ab7575..27c6cc9 100644 --- a/flutter/shell/platform/common/client_wrapper/include/flutter/basic_message_channel.h +++ b/flutter/shell/platform/common/client_wrapper/include/flutter/basic_message_channel.h @@ -7,6 +7,7 @@ #include #include +#include #include "binary_messenger.h" #include "message_codec.h" @@ -78,7 +79,8 @@ class BasicMessageChannel { void Send(const T& message, BinaryReply reply) { std::unique_ptr> raw_message = codec_->EncodeMessage(message); - messenger_->Send(name_, raw_message->data(), raw_message->size(), reply); + messenger_->Send(name_, raw_message->data(), raw_message->size(), + std::move(reply)); } // Registers a handler that should be called any time a message is @@ -97,7 +99,7 @@ class BasicMessageChannel { BinaryMessageHandler binary_handler = [handler, codec, channel_name]( const uint8_t* binary_message, const size_t binary_message_size, - BinaryReply binary_reply) { + const BinaryReply& binary_reply) { // Use this channel's codec to decode the message and build a reply // handler. std::unique_ptr message = diff --git a/flutter/shell/platform/common/client_wrapper/include/flutter/event_channel.h b/flutter/shell/platform/common/client_wrapper/include/flutter/event_channel.h index c96e640..1754596 100644 --- a/flutter/shell/platform/common/client_wrapper/include/flutter/event_channel.h +++ b/flutter/shell/platform/common/client_wrapper/include/flutter/event_channel.h @@ -69,7 +69,7 @@ class EventChannel { // Mutable state to track the handler's listening status. is_listening = bool(false)](const uint8_t* message, const size_t message_size, - BinaryReply reply) mutable { + const BinaryReply& reply) mutable { constexpr char kOnListenMethod[] = "listen"; constexpr char kOnCancelMethod[] = "cancel"; diff --git a/flutter/shell/platform/common/client_wrapper/include/flutter/method_result_functions.h b/flutter/shell/platform/common/client_wrapper/include/flutter/method_result_functions.h index a19cc34..57f6d0e 100644 --- a/flutter/shell/platform/common/client_wrapper/include/flutter/method_result_functions.h +++ b/flutter/shell/platform/common/client_wrapper/include/flutter/method_result_functions.h @@ -7,6 +7,7 @@ #include #include +#include #include "method_result.h" @@ -36,7 +37,7 @@ class MethodResultFunctions : public MethodResult { ResultHandlerNotImplemented on_not_implemented) : on_success_(on_success), on_error_(on_error), - on_not_implemented_(on_not_implemented) {} + on_not_implemented_(std::move(on_not_implemented)) {} virtual ~MethodResultFunctions() = default; diff --git a/flutter/shell/platform/common/client_wrapper/include/flutter/plugin_registrar.h b/flutter/shell/platform/common/client_wrapper/include/flutter/plugin_registrar.h index 15cf996..e21f472 100644 --- a/flutter/shell/platform/common/client_wrapper/include/flutter/plugin_registrar.h +++ b/flutter/shell/platform/common/client_wrapper/include/flutter/plugin_registrar.h @@ -54,7 +54,7 @@ class PluginRegistrar { void AddPlugin(std::unique_ptr plugin); protected: - FlutterDesktopPluginRegistrarRef registrar() { return registrar_; } + FlutterDesktopPluginRegistrarRef registrar() const { return registrar_; } // Destroys all owned plugins. Subclasses should call this at the beginning of // their destructors to prevent the possibility of an owned plugin trying to diff --git a/flutter/shell/platform/common/client_wrapper/include/flutter/texture_registrar.h b/flutter/shell/platform/common/client_wrapper/include/flutter/texture_registrar.h index 47daf7c..a536dcf 100644 --- a/flutter/shell/platform/common/client_wrapper/include/flutter/texture_registrar.h +++ b/flutter/shell/platform/common/client_wrapper/include/flutter/texture_registrar.h @@ -10,6 +10,7 @@ #include #include #include +#include #include namespace flutter { @@ -28,7 +29,7 @@ class PixelBufferTexture { // take care of proper synchronization. It also needs to be ensured that the // returned buffer isn't released prior to unregistering this texture. explicit PixelBufferTexture(CopyBufferCallback copy_buffer_callback) - : copy_buffer_callback_(copy_buffer_callback) {} + : copy_buffer_callback_(std::move(copy_buffer_callback)) {} // Returns the callback-provided FlutterDesktopPixelBuffer that contains the // actual pixel data. The intended surface size is specified by |width| and @@ -53,7 +54,7 @@ class GpuSurfaceTexture { GpuSurfaceTexture(FlutterDesktopGpuSurfaceType surface_type, ObtainDescriptorCallback obtain_descriptor_callback) : surface_type_(surface_type), - obtain_descriptor_callback_(obtain_descriptor_callback) {} + obtain_descriptor_callback_(std::move(obtain_descriptor_callback)) {} // Returns the callback-provided FlutterDesktopGpuSurfaceDescriptor that // contains the surface handle. The intended surface size is specified by diff --git a/flutter/shell/platform/common/incoming_message_dispatcher.h b/flutter/shell/platform/common/incoming_message_dispatcher.h index 90a8f90..2152b05 100644 --- a/flutter/shell/platform/common/incoming_message_dispatcher.h +++ b/flutter/shell/platform/common/incoming_message_dispatcher.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef FLUTTER_SHELL_PLATFORM_CPP_INCOMING_MESSAGE_DISPATCHER_H_ -#define FLUTTER_SHELL_PLATFORM_CPP_INCOMING_MESSAGE_DISPATCHER_H_ +#ifndef FLUTTER_SHELL_PLATFORM_COMMON_INCOMING_MESSAGE_DISPATCHER_H_ +#define FLUTTER_SHELL_PLATFORM_COMMON_INCOMING_MESSAGE_DISPATCHER_H_ #include #include @@ -75,4 +75,4 @@ class IncomingMessageDispatcher { } // namespace flutter -#endif // FLUTTER_SHELL_PLATFORM_CPP_INCOMING_MESSAGE_DISPATCHER_H_ +#endif // FLUTTER_SHELL_PLATFORM_COMMON_INCOMING_MESSAGE_DISPATCHER_H_ diff --git a/flutter/shell/platform/common/path_utils.h b/flutter/shell/platform/common/path_utils.h index 62cd3fd..e608430 100644 --- a/flutter/shell/platform/common/path_utils.h +++ b/flutter/shell/platform/common/path_utils.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef FLUTTER_SHELL_PLATFORM_GLFW_PATH_UTILS_H_ -#define FLUTTER_SHELL_PLATFORM_GLFW_PATH_UTILS_H_ +#ifndef FLUTTER_SHELL_PLATFORM_COMMON_PATH_UTILS_H_ +#define FLUTTER_SHELL_PLATFORM_COMMON_PATH_UTILS_H_ #include @@ -15,4 +15,4 @@ std::filesystem::path GetExecutableDirectory(); } // namespace flutter -#endif // FLUTTER_SHELL_PLATFORM_GLFW_PATH_UTILS_H_ +#endif // FLUTTER_SHELL_PLATFORM_COMMON_PATH_UTILS_H_ diff --git a/flutter/shell/platform/common/platform_provided_menu.h b/flutter/shell/platform/common/platform_provided_menu.h index 5c9b607..ac23df3 100644 --- a/flutter/shell/platform/common/platform_provided_menu.h +++ b/flutter/shell/platform/common/platform_provided_menu.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef PLATFORM_COMMON_PLATFORM_PROVIDED_MENU_H_ -#define PLATFORM_COMMON_PLATFORM_PROVIDED_MENU_H_ +#ifndef FLUTTER_SHELL_PLATFORM_COMMON_PLATFORM_PROVIDED_MENU_H_ +#define FLUTTER_SHELL_PLATFORM_COMMON_PLATFORM_PROVIDED_MENU_H_ namespace flutter { @@ -49,4 +49,4 @@ enum class PlatformProvidedMenu { } // namespace flutter -#endif // PLATFORM_COMMON_PLATFORM_provided_MENU_H_ +#endif // FLUTTER_SHELL_PLATFORM_COMMON_PLATFORM_PROVIDED_MENU_H_ diff --git a/flutter/shell/platform/common/public/flutter_messenger.h b/flutter/shell/platform/common/public/flutter_messenger.h index 019267c..b364a57 100644 --- a/flutter/shell/platform/common/public/flutter_messenger.h +++ b/flutter/shell/platform/common/public/flutter_messenger.h @@ -58,6 +58,8 @@ FLUTTER_EXPORT bool FlutterDesktopMessengerSend( const uint8_t* message, const size_t message_size); +// Sends a binary message to the Flutter side on the specified channel. +// The |reply| callback will be executed when a response is received. FLUTTER_EXPORT bool FlutterDesktopMessengerSendWithReply( FlutterDesktopMessengerRef messenger, const char* channel, diff --git a/flutter/shell/platform/common/text_input_model.cc b/flutter/shell/platform/common/text_input_model.cc index bfdc7c4..a21fe1f 100644 --- a/flutter/shell/platform/common/text_input_model.cc +++ b/flutter/shell/platform/common/text_input_model.cc @@ -69,15 +69,22 @@ void TextInputModel::BeginComposing() { composing_range_ = TextRange(selection_.start()); } -void TextInputModel::UpdateComposingText(const std::u16string& text) { +void TextInputModel::UpdateComposingText(const std::u16string& text, + const TextRange& selection) { // Preserve selection if we get a no-op update to the composing region. if (text.length() == 0 && composing_range_.collapsed()) { return; } - DeleteSelected(); - text_.replace(composing_range_.start(), composing_range_.length(), text); + const TextRange& rangeToDelete = + composing_range_.collapsed() ? selection_ : composing_range_; + text_.replace(rangeToDelete.start(), rangeToDelete.length(), text); composing_range_.set_end(composing_range_.start() + text.length()); - selection_ = TextRange(composing_range_.end()); + selection_ = TextRange(selection.start() + composing_range_.start(), + selection.extent() + composing_range_.start()); +} + +void TextInputModel::UpdateComposingText(const std::u16string& text) { + UpdateComposingText(text, TextRange(text.length())); } void TextInputModel::UpdateComposingText(const std::string& text) { diff --git a/flutter/shell/platform/common/text_input_model.h b/flutter/shell/platform/common/text_input_model.h index cd03e1f..2546e56 100644 --- a/flutter/shell/platform/common/text_input_model.h +++ b/flutter/shell/platform/common/text_input_model.h @@ -57,12 +57,17 @@ class TextInputModel { // are restricted to the composing range. void BeginComposing(); - // Replaces the composing range with new UTF-16 text. + // Replaces the composing range with new UTF-16 text, and sets the selection. // - // If a selection of non-zero length exists, it is deleted if the composing - // text is non-empty. The composing range is adjusted to the length of - // |text| and the selection base and offset are set to the end of the - // composing range. + // The given |text| replaces text within the current composing range, or the + // current selection if the text wasn't composing. The composing range is + // adjusted to the length of |text|, and the |selection| describes the new + // selection range, relative to the start of the new composing range. + void UpdateComposingText(const std::u16string& text, + const TextRange& selection); + + // Replaces the composing range with new UTF-16 text and sets the selection to + // the end of the composing text. void UpdateComposingText(const std::u16string& text); // Replaces the composing range with new UTF-8 text. diff --git a/flutter/shell/platform/embedder/embedder.h b/flutter/shell/platform/embedder/embedder.h index d8adf5e..d26e221 100644 --- a/flutter/shell/platform/embedder/embedder.h +++ b/flutter/shell/platform/embedder/embedder.h @@ -831,6 +831,53 @@ typedef struct { }; } FlutterRendererConfig; +typedef struct { + /// The size of this struct. + /// Must be sizeof(FlutterRemoveViewResult). + size_t struct_size; + + /// True if the remove view operation succeeded. + bool removed; + + /// The |FlutterRemoveViewInfo.user_data|. + void* user_data; +} FlutterRemoveViewResult; + +/// The callback invoked by the engine when the engine has attempted to remove +/// a view. +/// +/// The |FlutterRemoveViewResult| will be deallocated once the callback returns. +typedef void (*FlutterRemoveViewCallback)( + const FlutterRemoveViewResult* /* result */); + +typedef struct { + /// The size of this struct. + /// Must be sizeof(FlutterRemoveViewInfo). + size_t struct_size; + + /// The identifier for the view to remove. + /// + /// The implicit view cannot be removed if it is enabled. + FlutterViewId view_id; + + /// A baton that is not interpreted by the engine in any way. + /// It will be given back to the embedder in |remove_view_callback|. + /// Embedder resources may be associated with this baton. + void* user_data; + + /// Called once the engine has attempted to remove the view. + /// This callback is required. + /// + /// The embedder must not destroy the underlying surface until the callback is + /// invoked with a `removed` value of `true`. + /// + /// This callback is invoked on an internal engine managed thread. + /// Embedders must re-thread if necessary. + /// + /// The |result| argument will be deallocated when the callback returns. + FlutterRemoveViewCallback remove_view_callback; +} FlutterRemoveViewInfo; + /// Display refers to a graphics hardware system consisting of a framebuffer, /// typically a monitor or a screen. This ID is unique per display and is /// stable until the Flutter application restarts. @@ -859,6 +906,8 @@ typedef struct { double physical_view_inset_left; /// The identifier of the display the view is rendering on. FlutterEngineDisplayId display_id; + /// The view that this event is describing. + int64_t view_id; } FlutterWindowMetricsEvent; /// The phase of the pointer event. @@ -1736,8 +1785,30 @@ typedef struct { /// Extra information for the backing store that the embedder may /// use during presentation. FlutterBackingStorePresentInfo* backing_store_present_info; + + // Time in nanoseconds at which this frame is scheduled to be presented. 0 if + // not known. See FlutterEngineGetCurrentTime(). + uint64_t presentation_time; } FlutterLayer; +typedef struct { + /// The size of this struct. + /// Must be sizeof(FlutterPresentViewInfo). + size_t struct_size; + + /// The identifier of the target view. + FlutterViewId view_id; + + /// The layers that should be composited onto the view. + const FlutterLayer** layers; + + /// The count of layers. + size_t layers_count; + + /// The |FlutterCompositor.user_data|. + void* user_data; +} FlutterPresentViewInfo; + typedef bool (*FlutterBackingStoreCreateCallback)( const FlutterBackingStoreConfig* config, FlutterBackingStore* backing_store_out, @@ -1751,13 +1822,20 @@ typedef bool (*FlutterLayersPresentCallback)(const FlutterLayer** layers, size_t layers_count, void* user_data); +/// The callback invoked when the embedder should present to a view. +/// +/// The |FlutterPresentViewInfo| will be deallocated once the callback returns. +typedef bool (*FlutterPresentViewCallback)( + const FlutterPresentViewInfo* /* present info */); + typedef struct { /// This size of this struct. Must be sizeof(FlutterCompositor). size_t struct_size; /// A baton that in not interpreted by the engine in any way. If it passed /// back to the embedder in `FlutterCompositor.create_backing_store_callback`, - /// `FlutterCompositor.collect_backing_store_callback` and - /// `FlutterCompositor.present_layers_callback` + /// `FlutterCompositor.collect_backing_store_callback`, + /// `FlutterCompositor.present_layers_callback`, and + /// `FlutterCompositor.present_view_callback`. void* user_data; /// A callback invoked by the engine to obtain a backing store for a specific /// `FlutterLayer`. @@ -1771,10 +1849,23 @@ typedef struct { /// embedder may collect any resources associated with the backing store. FlutterBackingStoreCollectCallback collect_backing_store_callback; /// Callback invoked by the engine to composite the contents of each layer - /// onto the screen. + /// onto the implicit view. + /// + /// DEPRECATED: Use |present_view_callback| to support multiple views. + /// + /// Only one of `present_layers_callback` and `present_view_callback` may be + /// provided. Providing both is an error and engine initialization will + /// terminate. FlutterLayersPresentCallback present_layers_callback; /// Avoid caching backing stores provided by this compositor. bool avoid_backing_store_cache; + /// Callback invoked by the engine to composite the contents of each layer + /// onto the specified view. + /// + /// Only one of `present_layers_callback` and `present_view_callback` may be + /// provided. Providing both is an error and engine initialization will + /// terminate. + FlutterPresentViewCallback present_view_callback; } FlutterCompositor; typedef struct { @@ -2414,6 +2505,25 @@ FLUTTER_EXPORT FlutterEngineResult FlutterEngineRunInitialized( FLUTTER_API_SYMBOL(FlutterEngine) engine); +//------------------------------------------------------------------------------ +/// @brief Removes a view. +/// +/// This is an asynchronous operation. The view's resources must not +/// be cleaned up until the |remove_view_callback| is invoked with +/// a |removed| value of `true`. +/// +/// @param[in] engine A running engine instance. +/// @param[in] info The remove view arguments. This can be deallocated +/// once |FlutterEngineRemoveView| returns, before +/// |remove_view_callback| is invoked. +/// +/// @return The result of *starting* the asynchronous operation. If +/// `kSuccess`, the |remove_view_callback| will be invoked. +FLUTTER_EXPORT +FlutterEngineResult FlutterEngineRemoveView(FLUTTER_API_SYMBOL(FlutterEngine) + engine, + const FlutterRemoveViewInfo* info); + FLUTTER_EXPORT FlutterEngineResult FlutterEngineSendWindowMetricsEvent( FLUTTER_API_SYMBOL(FlutterEngine) engine,