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

Commit ead1348

Browse files
authored
Queue all semantic nodes & actions before completing batch (#35792)
1 parent 89909d9 commit ead1348

File tree

8 files changed

+149
-129
lines changed

8 files changed

+149
-129
lines changed

shell/platform/common/accessibility_bridge.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ void AccessibilityBridge::CommitUpdates() {
6363

6464
for (size_t i = results.size(); i > 0; i--) {
6565
for (SemanticsNode node : results[i - 1]) {
66-
ConvertFluterUpdate(node, update);
66+
ConvertFlutterUpdate(node, update);
6767
}
6868
}
6969

@@ -191,8 +191,8 @@ void AccessibilityBridge::GetSubTreeList(SemanticsNode target,
191191
}
192192
}
193193

194-
void AccessibilityBridge::ConvertFluterUpdate(const SemanticsNode& node,
195-
ui::AXTreeUpdate& tree_update) {
194+
void AccessibilityBridge::ConvertFlutterUpdate(const SemanticsNode& node,
195+
ui::AXTreeUpdate& tree_update) {
196196
ui::AXNodeData node_data;
197197
node_data.id = node.id;
198198
SetRoleFromFlutterUpdate(node_data, node);

shell/platform/common/accessibility_bridge.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,8 @@ class AccessibilityBridge
223223

224224
void InitAXTree(const ui::AXTreeUpdate& initial_state);
225225
void GetSubTreeList(SemanticsNode target, std::vector<SemanticsNode>& result);
226-
void ConvertFluterUpdate(const SemanticsNode& node,
227-
ui::AXTreeUpdate& tree_update);
226+
void ConvertFlutterUpdate(const SemanticsNode& node,
227+
ui::AXTreeUpdate& tree_update);
228228
void SetRoleFromFlutterUpdate(ui::AXNodeData& node_data,
229229
const SemanticsNode& node);
230230
void SetStateFromFlutterUpdate(ui::AXNodeData& node_data,

shell/platform/embedder/embedder.cc

Lines changed: 97 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1400,88 +1400,110 @@ FlutterEngineResult FlutterEngineInitialize(size_t version,
14001400
settings.log_tag = SAFE_ACCESS(args, log_tag, nullptr);
14011401
}
14021402

1403-
flutter::PlatformViewEmbedder::UpdateSemanticsNodesCallback
1404-
update_semantics_nodes_callback = nullptr;
1403+
FlutterUpdateSemanticsNodeCallback update_semantics_node_callback = nullptr;
14051404
if (SAFE_ACCESS(args, update_semantics_node_callback, nullptr) != nullptr) {
1406-
update_semantics_nodes_callback =
1407-
[ptr = args->update_semantics_node_callback,
1408-
user_data](flutter::SemanticsNodeUpdates update) {
1409-
for (const auto& value : update) {
1410-
const auto& node = value.second;
1411-
SkMatrix transform = node.transform.asM33();
1412-
FlutterTransformation flutter_transform{
1413-
transform.get(SkMatrix::kMScaleX),
1414-
transform.get(SkMatrix::kMSkewX),
1415-
transform.get(SkMatrix::kMTransX),
1416-
transform.get(SkMatrix::kMSkewY),
1417-
transform.get(SkMatrix::kMScaleY),
1418-
transform.get(SkMatrix::kMTransY),
1419-
transform.get(SkMatrix::kMPersp0),
1420-
transform.get(SkMatrix::kMPersp1),
1421-
transform.get(SkMatrix::kMPersp2)};
1422-
const FlutterSemanticsNode embedder_node{
1423-
sizeof(FlutterSemanticsNode),
1424-
node.id,
1425-
static_cast<FlutterSemanticsFlag>(node.flags),
1426-
static_cast<FlutterSemanticsAction>(node.actions),
1427-
node.textSelectionBase,
1428-
node.textSelectionExtent,
1429-
node.scrollChildren,
1430-
node.scrollIndex,
1431-
node.scrollPosition,
1432-
node.scrollExtentMax,
1433-
node.scrollExtentMin,
1434-
node.elevation,
1435-
node.thickness,
1436-
node.label.c_str(),
1437-
node.hint.c_str(),
1438-
node.value.c_str(),
1439-
node.increasedValue.c_str(),
1440-
node.decreasedValue.c_str(),
1441-
static_cast<FlutterTextDirection>(node.textDirection),
1442-
FlutterRect{node.rect.fLeft, node.rect.fTop, node.rect.fRight,
1443-
node.rect.fBottom},
1444-
flutter_transform,
1445-
node.childrenInTraversalOrder.size(),
1446-
node.childrenInTraversalOrder.data(),
1447-
node.childrenInHitTestOrder.data(),
1448-
node.customAccessibilityActions.size(),
1449-
node.customAccessibilityActions.data(),
1450-
node.platformViewId,
1451-
};
1452-
ptr(&embedder_node, user_data);
1453-
}
1454-
const FlutterSemanticsNode batch_end_sentinel = {
1455-
sizeof(FlutterSemanticsNode),
1456-
kFlutterSemanticsNodeIdBatchEnd,
1457-
};
1458-
ptr(&batch_end_sentinel, user_data);
1459-
};
1405+
update_semantics_node_callback = args->update_semantics_node_callback;
14601406
}
14611407

1462-
flutter::PlatformViewEmbedder::UpdateSemanticsCustomActionsCallback
1463-
update_semantics_custom_actions_callback = nullptr;
1408+
FlutterUpdateSemanticsCustomActionCallback
1409+
update_semantics_custom_action_callback = nullptr;
14641410
if (SAFE_ACCESS(args, update_semantics_custom_action_callback, nullptr) !=
14651411
nullptr) {
1466-
update_semantics_custom_actions_callback =
1467-
[ptr = args->update_semantics_custom_action_callback,
1468-
user_data](flutter::CustomAccessibilityActionUpdates actions) {
1469-
for (const auto& value : actions) {
1470-
const auto& action = value.second;
1471-
const FlutterSemanticsCustomAction embedder_action = {
1412+
update_semantics_custom_action_callback =
1413+
args->update_semantics_custom_action_callback;
1414+
}
1415+
1416+
flutter::PlatformViewEmbedder::UpdateSemanticsCallback
1417+
update_semantics_callback = nullptr;
1418+
if (update_semantics_node_callback != nullptr ||
1419+
update_semantics_custom_action_callback != nullptr) {
1420+
update_semantics_callback =
1421+
[update_semantics_node_callback,
1422+
update_semantics_custom_action_callback,
1423+
user_data](flutter::SemanticsNodeUpdates update,
1424+
flutter::CustomAccessibilityActionUpdates actions) {
1425+
// First, queue all node and custom action updates.
1426+
if (update_semantics_node_callback != nullptr) {
1427+
for (const auto& value : update) {
1428+
const auto& node = value.second;
1429+
SkMatrix transform = node.transform.asM33();
1430+
FlutterTransformation flutter_transform{
1431+
transform.get(SkMatrix::kMScaleX),
1432+
transform.get(SkMatrix::kMSkewX),
1433+
transform.get(SkMatrix::kMTransX),
1434+
transform.get(SkMatrix::kMSkewY),
1435+
transform.get(SkMatrix::kMScaleY),
1436+
transform.get(SkMatrix::kMTransY),
1437+
transform.get(SkMatrix::kMPersp0),
1438+
transform.get(SkMatrix::kMPersp1),
1439+
transform.get(SkMatrix::kMPersp2)};
1440+
const FlutterSemanticsNode embedder_node{
1441+
sizeof(FlutterSemanticsNode),
1442+
node.id,
1443+
static_cast<FlutterSemanticsFlag>(node.flags),
1444+
static_cast<FlutterSemanticsAction>(node.actions),
1445+
node.textSelectionBase,
1446+
node.textSelectionExtent,
1447+
node.scrollChildren,
1448+
node.scrollIndex,
1449+
node.scrollPosition,
1450+
node.scrollExtentMax,
1451+
node.scrollExtentMin,
1452+
node.elevation,
1453+
node.thickness,
1454+
node.label.c_str(),
1455+
node.hint.c_str(),
1456+
node.value.c_str(),
1457+
node.increasedValue.c_str(),
1458+
node.decreasedValue.c_str(),
1459+
static_cast<FlutterTextDirection>(node.textDirection),
1460+
FlutterRect{node.rect.fLeft, node.rect.fTop, node.rect.fRight,
1461+
node.rect.fBottom},
1462+
flutter_transform,
1463+
node.childrenInTraversalOrder.size(),
1464+
node.childrenInTraversalOrder.data(),
1465+
node.childrenInHitTestOrder.data(),
1466+
node.customAccessibilityActions.size(),
1467+
node.customAccessibilityActions.data(),
1468+
node.platformViewId,
1469+
};
1470+
update_semantics_node_callback(&embedder_node, user_data);
1471+
}
1472+
}
1473+
1474+
if (update_semantics_custom_action_callback != nullptr) {
1475+
for (const auto& value : actions) {
1476+
const auto& action = value.second;
1477+
const FlutterSemanticsCustomAction embedder_action = {
1478+
sizeof(FlutterSemanticsCustomAction),
1479+
action.id,
1480+
static_cast<FlutterSemanticsAction>(action.overrideId),
1481+
action.label.c_str(),
1482+
action.hint.c_str(),
1483+
};
1484+
update_semantics_custom_action_callback(&embedder_action,
1485+
user_data);
1486+
}
1487+
}
1488+
1489+
// Second, mark node and action batches completed now that all
1490+
// updates are queued.
1491+
if (update_semantics_node_callback != nullptr) {
1492+
const FlutterSemanticsNode batch_end_sentinel = {
1493+
sizeof(FlutterSemanticsNode),
1494+
kFlutterSemanticsNodeIdBatchEnd,
1495+
};
1496+
update_semantics_node_callback(&batch_end_sentinel, user_data);
1497+
}
1498+
1499+
if (update_semantics_custom_action_callback != nullptr) {
1500+
const FlutterSemanticsCustomAction batch_end_sentinel = {
14721501
sizeof(FlutterSemanticsCustomAction),
1473-
action.id,
1474-
static_cast<FlutterSemanticsAction>(action.overrideId),
1475-
action.label.c_str(),
1476-
action.hint.c_str(),
1502+
kFlutterSemanticsCustomActionIdBatchEnd,
14771503
};
1478-
ptr(&embedder_action, user_data);
1504+
update_semantics_custom_action_callback(&batch_end_sentinel,
1505+
user_data);
14791506
}
1480-
const FlutterSemanticsCustomAction batch_end_sentinel = {
1481-
sizeof(FlutterSemanticsCustomAction),
1482-
kFlutterSemanticsCustomActionIdBatchEnd,
1483-
};
1484-
ptr(&batch_end_sentinel, user_data);
14851507
};
14861508
}
14871509

@@ -1576,8 +1598,7 @@ FlutterEngineResult FlutterEngineInitialize(size_t version,
15761598

15771599
flutter::PlatformViewEmbedder::PlatformDispatchTable platform_dispatch_table =
15781600
{
1579-
update_semantics_nodes_callback, //
1580-
update_semantics_custom_actions_callback, //
1601+
update_semantics_callback, //
15811602
platform_message_response_callback, //
15821603
vsync_callback, //
15831604
compute_platform_resolved_locale_callback, //

shell/platform/embedder/platform_view_embedder.cc

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,9 @@ PlatformViewEmbedder::~PlatformViewEmbedder() = default;
6767
void PlatformViewEmbedder::UpdateSemantics(
6868
flutter::SemanticsNodeUpdates update,
6969
flutter::CustomAccessibilityActionUpdates actions) {
70-
if (platform_dispatch_table_.update_semantics_nodes_callback != nullptr) {
71-
platform_dispatch_table_.update_semantics_nodes_callback(std::move(update));
72-
}
73-
if (platform_dispatch_table_.update_semantics_custom_actions_callback !=
74-
nullptr) {
75-
platform_dispatch_table_.update_semantics_custom_actions_callback(
76-
std::move(actions));
70+
if (platform_dispatch_table_.update_semantics_callback != nullptr) {
71+
platform_dispatch_table_.update_semantics_callback(std::move(update),
72+
std::move(actions));
7773
}
7874
}
7975

shell/platform/embedder/platform_view_embedder.h

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,9 @@ namespace flutter {
3131

3232
class PlatformViewEmbedder final : public PlatformView {
3333
public:
34-
using UpdateSemanticsNodesCallback =
35-
std::function<void(flutter::SemanticsNodeUpdates update)>;
36-
using UpdateSemanticsCustomActionsCallback =
37-
std::function<void(flutter::CustomAccessibilityActionUpdates actions)>;
34+
using UpdateSemanticsCallback =
35+
std::function<void(flutter::SemanticsNodeUpdates update,
36+
flutter::CustomAccessibilityActionUpdates actions)>;
3837
using PlatformMessageResponseCallback =
3938
std::function<void(std::unique_ptr<PlatformMessage>)>;
4039
using ComputePlatformResolvedLocaleCallback =
@@ -43,9 +42,7 @@ class PlatformViewEmbedder final : public PlatformView {
4342
using OnPreEngineRestartCallback = std::function<void()>;
4443

4544
struct PlatformDispatchTable {
46-
UpdateSemanticsNodesCallback update_semantics_nodes_callback; // optional
47-
UpdateSemanticsCustomActionsCallback
48-
update_semantics_custom_actions_callback; // optional
45+
UpdateSemanticsCallback update_semantics_callback; // optional
4946
PlatformMessageResponseCallback
5047
platform_message_response_callback; // optional
5148
VsyncWaiterEmbedder::VsyncCallback vsync_callback; // optional

shell/platform/embedder/tests/embedder_a11y_unittests.cc

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -120,40 +120,47 @@ TEST_F(EmbedderA11yTest, A11yTreeIsConsistent) {
120120
latch.Wait();
121121

122122
// Wait for UpdateSemantics callback on platform (current) thread.
123-
int node_count = 0;
124123
int node_batch_end_count = 0;
125-
context.SetSemanticsNodeCallback(
126-
[&node_count, &node_batch_end_count](const FlutterSemanticsNode* node) {
127-
if (node->id == kFlutterSemanticsNodeIdBatchEnd) {
128-
++node_batch_end_count;
129-
} else {
130-
++node_count;
131-
ASSERT_EQ(1.0, node->transform.scaleX);
132-
ASSERT_EQ(2.0, node->transform.skewX);
133-
ASSERT_EQ(3.0, node->transform.transX);
134-
ASSERT_EQ(4.0, node->transform.skewY);
135-
ASSERT_EQ(5.0, node->transform.scaleY);
136-
ASSERT_EQ(6.0, node->transform.transY);
137-
ASSERT_EQ(7.0, node->transform.pers0);
138-
ASSERT_EQ(8.0, node->transform.pers1);
139-
ASSERT_EQ(9.0, node->transform.pers2);
140-
141-
if (node->id == 128) {
142-
ASSERT_EQ(0x3f3, node->platform_view_id);
143-
} else {
144-
ASSERT_EQ(0, node->platform_view_id);
145-
}
146-
}
147-
});
124+
int action_batch_end_count = 0;
125+
126+
int node_count = 0;
127+
context.SetSemanticsNodeCallback([&](const FlutterSemanticsNode* node) {
128+
if (node->id == kFlutterSemanticsNodeIdBatchEnd) {
129+
++node_batch_end_count;
130+
} else {
131+
// Batches should be completed after all nodes are received.
132+
ASSERT_EQ(0, node_batch_end_count);
133+
ASSERT_EQ(0, action_batch_end_count);
134+
135+
++node_count;
136+
ASSERT_EQ(1.0, node->transform.scaleX);
137+
ASSERT_EQ(2.0, node->transform.skewX);
138+
ASSERT_EQ(3.0, node->transform.transX);
139+
ASSERT_EQ(4.0, node->transform.skewY);
140+
ASSERT_EQ(5.0, node->transform.scaleY);
141+
ASSERT_EQ(6.0, node->transform.transY);
142+
ASSERT_EQ(7.0, node->transform.pers0);
143+
ASSERT_EQ(8.0, node->transform.pers1);
144+
ASSERT_EQ(9.0, node->transform.pers2);
145+
146+
if (node->id == 128) {
147+
ASSERT_EQ(0x3f3, node->platform_view_id);
148+
} else {
149+
ASSERT_EQ(0, node->platform_view_id);
150+
}
151+
}
152+
});
148153

149154
int action_count = 0;
150-
int action_batch_end_count = 0;
151155
context.SetSemanticsCustomActionCallback(
152-
[&action_count,
153-
&action_batch_end_count](const FlutterSemanticsCustomAction* action) {
156+
[&](const FlutterSemanticsCustomAction* action) {
154157
if (action->id == kFlutterSemanticsCustomActionIdBatchEnd) {
155158
++action_batch_end_count;
156159
} else {
160+
// Batches should be completed after all actions are received.
161+
ASSERT_EQ(0, node_batch_end_count);
162+
ASSERT_EQ(0, action_batch_end_count);
163+
157164
++action_count;
158165
}
159166
});

shell/platform/embedder/tests/embedder_test_context.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,14 +119,14 @@ void EmbedderTestContext::AddNativeCallback(const char* name,
119119
}
120120

121121
void EmbedderTestContext::SetSemanticsNodeCallback(
122-
const SemanticsNodeCallback& update_semantics_node_callback) {
123-
update_semantics_node_callback_ = update_semantics_node_callback;
122+
SemanticsNodeCallback update_semantics_node_callback) {
123+
update_semantics_node_callback_ = std::move(update_semantics_node_callback);
124124
}
125125

126126
void EmbedderTestContext::SetSemanticsCustomActionCallback(
127-
const SemanticsActionCallback& update_semantics_custom_action_callback) {
127+
SemanticsActionCallback update_semantics_custom_action_callback) {
128128
update_semantics_custom_action_callback_ =
129-
update_semantics_custom_action_callback;
129+
std::move(update_semantics_custom_action_callback);
130130
}
131131

132132
void EmbedderTestContext::SetPlatformMessageCallback(

shell/platform/embedder/tests/embedder_test_context.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,10 @@ class EmbedderTestContext {
7171

7272
void AddNativeCallback(const char* name, Dart_NativeFunction function);
7373

74-
void SetSemanticsNodeCallback(
75-
const SemanticsNodeCallback& update_semantics_node);
74+
void SetSemanticsNodeCallback(SemanticsNodeCallback update_semantics_node);
7675

7776
void SetSemanticsCustomActionCallback(
78-
const SemanticsActionCallback& semantics_custom_action);
77+
SemanticsActionCallback semantics_custom_action);
7978

8079
void SetPlatformMessageCallback(
8180
const std::function<void(const FlutterPlatformMessage*)>& callback);

0 commit comments

Comments
 (0)