Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

[Embedder] Refactor how semantic updates are mapped #44553

Merged
merged 3 commits into from
Aug 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -2845,6 +2845,8 @@ ORIGIN: ../../../flutter/shell/platform/embedder/embedder_render_target_impeller
ORIGIN: ../../../flutter/shell/platform/embedder/embedder_render_target_impeller.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/embedder/embedder_render_target_skia.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/embedder/embedder_render_target_skia.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/embedder/embedder_semantics_update.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/embedder/embedder_semantics_update.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/embedder/embedder_struct_macros.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/embedder/embedder_surface.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/embedder/embedder_surface.h + ../../../flutter/LICENSE
Expand Down Expand Up @@ -5581,6 +5583,8 @@ FILE: ../../../flutter/shell/platform/embedder/embedder_render_target_impeller.c
FILE: ../../../flutter/shell/platform/embedder/embedder_render_target_impeller.h
FILE: ../../../flutter/shell/platform/embedder/embedder_render_target_skia.cc
FILE: ../../../flutter/shell/platform/embedder/embedder_render_target_skia.h
FILE: ../../../flutter/shell/platform/embedder/embedder_semantics_update.cc
FILE: ../../../flutter/shell/platform/embedder/embedder_semantics_update.h
FILE: ../../../flutter/shell/platform/embedder/embedder_struct_macros.h
FILE: ../../../flutter/shell/platform/embedder/embedder_surface.cc
FILE: ../../../flutter/shell/platform/embedder/embedder_surface.h
Expand Down
2 changes: 2 additions & 0 deletions shell/platform/embedder/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ template("embedder_source_set") {
"embedder_render_target_cache.h",
"embedder_render_target_skia.cc",
"embedder_render_target_skia.h",
"embedder_semantics_update.cc",
"embedder_semantics_update.h",
"embedder_struct_macros.h",
"embedder_surface.cc",
"embedder_surface.h",
Expand Down
272 changes: 53 additions & 219 deletions shell/platform/embedder/embedder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ extern const intptr_t kPlatformStrongDillSize;
#include "flutter/shell/platform/embedder/embedder_platform_message_response.h"
#include "flutter/shell/platform/embedder/embedder_render_target.h"
#include "flutter/shell/platform/embedder/embedder_render_target_skia.h"
#include "flutter/shell/platform/embedder/embedder_semantics_update.h"
#include "flutter/shell/platform/embedder/embedder_struct_macros.h"
#include "flutter/shell/platform/embedder/embedder_task_runner.h"
#include "flutter/shell/platform/embedder/embedder_thread_host.h"
Expand Down Expand Up @@ -1494,214 +1495,11 @@ void PopulateAOTSnapshotMappingCallbacks(
}
}

// Translates engine semantic nodes to embedder semantic nodes.
FlutterSemanticsNode CreateEmbedderSemanticsNode(
const flutter::SemanticsNode& node) {
SkMatrix transform = node.transform.asM33();
FlutterTransformation flutter_transform{
transform.get(SkMatrix::kMScaleX), transform.get(SkMatrix::kMSkewX),
transform.get(SkMatrix::kMTransX), transform.get(SkMatrix::kMSkewY),
transform.get(SkMatrix::kMScaleY), transform.get(SkMatrix::kMTransY),
transform.get(SkMatrix::kMPersp0), transform.get(SkMatrix::kMPersp1),
transform.get(SkMatrix::kMPersp2)};

// Do not add new members to FlutterSemanticsNode.
// This would break the forward compatibility of FlutterSemanticsUpdate.
// All new members must be added to FlutterSemanticsNode2 instead.
return {
sizeof(FlutterSemanticsNode),
node.id,
static_cast<FlutterSemanticsFlag>(node.flags),
static_cast<FlutterSemanticsAction>(node.actions),
node.textSelectionBase,
node.textSelectionExtent,
node.scrollChildren,
node.scrollIndex,
node.scrollPosition,
node.scrollExtentMax,
node.scrollExtentMin,
node.elevation,
node.thickness,
node.label.c_str(),
node.hint.c_str(),
node.value.c_str(),
node.increasedValue.c_str(),
node.decreasedValue.c_str(),
static_cast<FlutterTextDirection>(node.textDirection),
FlutterRect{node.rect.fLeft, node.rect.fTop, node.rect.fRight,
node.rect.fBottom},
flutter_transform,
node.childrenInTraversalOrder.size(),
node.childrenInTraversalOrder.data(),
node.childrenInHitTestOrder.data(),
node.customAccessibilityActions.size(),
node.customAccessibilityActions.data(),
node.platformViewId,
node.tooltip.c_str(),
};
}

// Translates engine semantic nodes to embedder semantic nodes.
FlutterSemanticsNode2 CreateEmbedderSemanticsNode2(
const flutter::SemanticsNode& node) {
SkMatrix transform = node.transform.asM33();
FlutterTransformation flutter_transform{
transform.get(SkMatrix::kMScaleX), transform.get(SkMatrix::kMSkewX),
transform.get(SkMatrix::kMTransX), transform.get(SkMatrix::kMSkewY),
transform.get(SkMatrix::kMScaleY), transform.get(SkMatrix::kMTransY),
transform.get(SkMatrix::kMPersp0), transform.get(SkMatrix::kMPersp1),
transform.get(SkMatrix::kMPersp2)};
return {
sizeof(FlutterSemanticsNode2),
node.id,
static_cast<FlutterSemanticsFlag>(node.flags),
static_cast<FlutterSemanticsAction>(node.actions),
node.textSelectionBase,
node.textSelectionExtent,
node.scrollChildren,
node.scrollIndex,
node.scrollPosition,
node.scrollExtentMax,
node.scrollExtentMin,
node.elevation,
node.thickness,
node.label.c_str(),
node.hint.c_str(),
node.value.c_str(),
node.increasedValue.c_str(),
node.decreasedValue.c_str(),
static_cast<FlutterTextDirection>(node.textDirection),
FlutterRect{node.rect.fLeft, node.rect.fTop, node.rect.fRight,
node.rect.fBottom},
flutter_transform,
node.childrenInTraversalOrder.size(),
node.childrenInTraversalOrder.data(),
node.childrenInHitTestOrder.data(),
node.customAccessibilityActions.size(),
node.customAccessibilityActions.data(),
node.platformViewId,
node.tooltip.c_str(),
};
}

// Translates engine semantic custom actions to embedder semantic custom
// actions.
FlutterSemanticsCustomAction CreateEmbedderSemanticsCustomAction(
const flutter::CustomAccessibilityAction& action) {
// Do not add new members to FlutterSemanticsCustomAction.
// This would break the forward compatibility of FlutterSemanticsUpdate.
// All new members must be added to FlutterSemanticsCustomAction2 instead.
return {
sizeof(FlutterSemanticsCustomAction),
action.id,
static_cast<FlutterSemanticsAction>(action.overrideId),
action.label.c_str(),
action.hint.c_str(),
};
}

// Translates engine semantic custom actions to embedder semantic custom
// actions.
FlutterSemanticsCustomAction2 CreateEmbedderSemanticsCustomAction2(
const flutter::CustomAccessibilityAction& action) {
return {
sizeof(FlutterSemanticsCustomAction2),
action.id,
static_cast<FlutterSemanticsAction>(action.overrideId),
action.label.c_str(),
action.hint.c_str(),
};
}

// Create a callback to notify the embedder of semantic updates
// using the deprecated embedder callback 'update_semantics_callback'.
flutter::PlatformViewEmbedder::UpdateSemanticsCallback
CreateNewEmbedderSemanticsUpdateCallback(
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was renamed to CreateEmbedderSemanticsUpdateCallbackV2 and moved down to below CreateEmbedderSemanticsUpdateCallbackV1.

FlutterUpdateSemanticsCallback update_semantics_callback,
void* user_data) {
return [update_semantics_callback, user_data](
const flutter::SemanticsNodeUpdates& nodes,
const flutter::CustomAccessibilityActionUpdates& actions) {
std::vector<FlutterSemanticsNode> embedder_nodes;
for (const auto& value : nodes) {
embedder_nodes.push_back(CreateEmbedderSemanticsNode(value.second));
}

std::vector<FlutterSemanticsCustomAction> embedder_custom_actions;
for (const auto& value : actions) {
embedder_custom_actions.push_back(
CreateEmbedderSemanticsCustomAction(value.second));
}

FlutterSemanticsUpdate update{
.struct_size = sizeof(FlutterSemanticsUpdate),
.nodes_count = embedder_nodes.size(),
.nodes = embedder_nodes.data(),
.custom_actions_count = embedder_custom_actions.size(),
.custom_actions = embedder_custom_actions.data(),
};

update_semantics_callback(&update, user_data);
};
}

// Create a callback to notify the embedder of semantic updates
// using the new embedder callback 'update_semantics_callback2'.
flutter::PlatformViewEmbedder::UpdateSemanticsCallback
CreateNewEmbedderSemanticsUpdateCallback2(
Copy link
Member Author

@loic-sharma loic-sharma Aug 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was renamed to CreateEmbedderSemanticsUpdateCallbackV3 and moved down to below CreateEmbedderSemanticsUpdateCallbackV2.

FlutterUpdateSemanticsCallback2 update_semantics_callback,
void* user_data) {
return [update_semantics_callback, user_data](
const flutter::SemanticsNodeUpdates& nodes,
const flutter::CustomAccessibilityActionUpdates& actions) {
std::vector<FlutterSemanticsNode2> embedder_nodes;
std::vector<FlutterSemanticsCustomAction2> embedder_custom_actions;

embedder_nodes.reserve(nodes.size());
embedder_custom_actions.reserve(actions.size());

for (const auto& value : nodes) {
embedder_nodes.push_back(CreateEmbedderSemanticsNode2(value.second));
}

for (const auto& value : actions) {
embedder_custom_actions.push_back(
CreateEmbedderSemanticsCustomAction2(value.second));
}

// Provide the embedder an array of pointers to maintain full forward and
// backward compatibility even if new members are added to semantic structs.
std::vector<FlutterSemanticsNode2*> embedder_node_pointers;
std::vector<FlutterSemanticsCustomAction2*> embedder_custom_action_pointers;

embedder_node_pointers.reserve(embedder_nodes.size());
embedder_custom_action_pointers.reserve(embedder_custom_actions.size());

for (auto& node : embedder_nodes) {
embedder_node_pointers.push_back(&node);
}

for (auto& action : embedder_custom_actions) {
embedder_custom_action_pointers.push_back(&action);
}

FlutterSemanticsUpdate2 update{
.struct_size = sizeof(FlutterSemanticsUpdate2),
.node_count = embedder_node_pointers.size(),
.nodes = embedder_node_pointers.data(),
.custom_action_count = embedder_custom_action_pointers.size(),
.custom_actions = embedder_custom_action_pointers.data(),
};

update_semantics_callback(&update, user_data);
};
}

// Create a callback to notify the embedder of semantic updates
// using the legacy embedder callbacks 'update_semantics_node_callback' and
// 'update_semantics_custom_action_callback'.
flutter::PlatformViewEmbedder::UpdateSemanticsCallback
CreateLegacyEmbedderSemanticsUpdateCallback(
CreateEmbedderSemanticsUpdateCallbackV1(
FlutterUpdateSemanticsNodeCallback update_semantics_node_callback,
FlutterUpdateSemanticsCustomActionCallback
update_semantics_custom_action_callback,
Expand All @@ -1710,20 +1508,20 @@ CreateLegacyEmbedderSemanticsUpdateCallback(
update_semantics_custom_action_callback,
user_data](const flutter::SemanticsNodeUpdates& nodes,
const flutter::CustomAccessibilityActionUpdates& actions) {
flutter::EmbedderSemanticsUpdate update{nodes, actions};
FlutterSemanticsUpdate* update_ptr = update.get();

// First, queue all node and custom action updates.
if (update_semantics_node_callback != nullptr) {
for (const auto& value : nodes) {
const FlutterSemanticsNode embedder_node =
CreateEmbedderSemanticsNode(value.second);
update_semantics_node_callback(&embedder_node, user_data);
for (size_t i = 0; i < update_ptr->nodes_count; i++) {
update_semantics_node_callback(&update_ptr->nodes[i], user_data);
}
}

if (update_semantics_custom_action_callback != nullptr) {
for (const auto& value : actions) {
const FlutterSemanticsCustomAction embedder_action =
CreateEmbedderSemanticsCustomAction(value.second);
update_semantics_custom_action_callback(&embedder_action, user_data);
for (size_t i = 0; i < update_ptr->custom_actions_count; i++) {
update_semantics_custom_action_callback(&update_ptr->custom_actions[i],
user_data);
}
}

Expand All @@ -1747,26 +1545,62 @@ CreateLegacyEmbedderSemanticsUpdateCallback(
};
}

// Create a callback to notify the embedder of semantic updates
// using the deprecated embedder callback 'update_semantics_callback'.
flutter::PlatformViewEmbedder::UpdateSemanticsCallback
CreateEmbedderSemanticsUpdateCallbackV2(
FlutterUpdateSemanticsCallback update_semantics_callback,
void* user_data) {
return [update_semantics_callback, user_data](
const flutter::SemanticsNodeUpdates& nodes,
const flutter::CustomAccessibilityActionUpdates& actions) {
flutter::EmbedderSemanticsUpdate update{nodes, actions};

update_semantics_callback(update.get(), user_data);
};
}

// Create a callback to notify the embedder of semantic updates
// using the new embedder callback 'update_semantics_callback2'.
flutter::PlatformViewEmbedder::UpdateSemanticsCallback
CreateEmbedderSemanticsUpdateCallbackV3(
FlutterUpdateSemanticsCallback2 update_semantics_callback,
void* user_data) {
return [update_semantics_callback, user_data](
const flutter::SemanticsNodeUpdates& nodes,
const flutter::CustomAccessibilityActionUpdates& actions) {
flutter::EmbedderSemanticsUpdate2 update{nodes, actions};

update_semantics_callback(update.get(), user_data);
};
}

// Creates a callback that receives semantic updates from the engine
// and notifies the embedder's callback(s). Returns null if the embedder
// did not register any callbacks.
flutter::PlatformViewEmbedder::UpdateSemanticsCallback
CreateEmbedderSemanticsUpdateCallback(const FlutterProjectArgs* args,
void* user_data) {
// The embedder can register the new callback, or the legacy callbacks, or
// nothing at all. Handle the case where the embedder registered the 'new'
// callback.
// There are three variants for the embedder API's semantic update callbacks.
// Create a callback that maps to the embedder's desired semantic update API.
//
// Handle the case where the embedder registered the callback
// 'updated_semantics_callback2'
if (SAFE_ACCESS(args, update_semantics_callback2, nullptr) != nullptr) {
return CreateNewEmbedderSemanticsUpdateCallback2(
return CreateEmbedderSemanticsUpdateCallbackV3(
args->update_semantics_callback2, user_data);
}

// Handle the case where the embedder registered the deprecated callback
// 'update_semantics_callback'.
if (SAFE_ACCESS(args, update_semantics_callback, nullptr) != nullptr) {
return CreateNewEmbedderSemanticsUpdateCallback(
return CreateEmbedderSemanticsUpdateCallbackV2(
args->update_semantics_callback, user_data);
}

// Handle the case where the embedder registered 'legacy' callbacks.
// Handle the case where the embedder registered the deprecated callbacks
// 'update_semantics_node_callback' and
// 'update_semantics_custom_action_callback'.
FlutterUpdateSemanticsNodeCallback update_semantics_node_callback = nullptr;
if (SAFE_ACCESS(args, update_semantics_node_callback, nullptr) != nullptr) {
update_semantics_node_callback = args->update_semantics_node_callback;
Expand All @@ -1782,7 +1616,7 @@ CreateEmbedderSemanticsUpdateCallback(const FlutterProjectArgs* args,

if (update_semantics_node_callback != nullptr ||
update_semantics_custom_action_callback != nullptr) {
return CreateLegacyEmbedderSemanticsUpdateCallback(
return CreateEmbedderSemanticsUpdateCallbackV1(
update_semantics_node_callback, update_semantics_custom_action_callback,
user_data);
}
Expand Down
Loading