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

Commit ab5806c

Browse files
committed
[macOS] Move to new update semantics embedder API
1 parent 206ef0f commit ab5806c

File tree

2 files changed

+53
-76
lines changed

2 files changed

+53
-76
lines changed

shell/platform/darwin/macos/framework/Source/FlutterEngine.mm

Lines changed: 26 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -304,16 +304,11 @@ - (BOOL)runWithEntrypoint:(NSString*)entrypoint {
304304
flutterArguments.command_line_argc = static_cast<int>(argv.size());
305305
flutterArguments.command_line_argv = argv.empty() ? nullptr : argv.data();
306306
flutterArguments.platform_message_callback = (FlutterPlatformMessageCallback)OnPlatformMessage;
307-
flutterArguments.update_semantics_node_callback = [](const FlutterSemanticsNode* node,
308-
void* user_data) {
307+
flutterArguments.update_semantics_callback = [](const FlutterSemanticsUpdate* update,
308+
void* user_data) {
309309
FlutterEngine* engine = (__bridge FlutterEngine*)user_data;
310-
[engine updateSemanticsNode:node];
310+
[engine updateSemantics:update];
311311
};
312-
flutterArguments.update_semantics_custom_action_callback =
313-
[](const FlutterSemanticsCustomAction* action, void* user_data) {
314-
FlutterEngine* engine = (__bridge FlutterEngine*)user_data;
315-
[engine updateSemanticsCustomActions:action];
316-
};
317312
flutterArguments.custom_dart_entrypoint = entrypoint.UTF8String;
318313
flutterArguments.shutdown_dart_vm_when_done = true;
319314
flutterArguments.dart_entrypoint_argc = dartEntrypointArgs.size();
@@ -921,37 +916,34 @@ - (BOOL)unregisterTextureWithID:(int64_t)textureID {
921916
return _embedderAPI.UnregisterExternalTexture(_engine, textureID) == kSuccess;
922917
}
923918

924-
- (void)updateSemanticsNode:(const FlutterSemanticsNode*)node {
919+
- (void)updateSemantics:(const FlutterSemanticsUpdate*)update {
925920
NSAssert(_bridge, @"The accessibility bridge must be initialized.");
926-
if (node->id == kFlutterSemanticsNodeIdBatchEnd) {
927-
return;
921+
for (size_t i = 0; i < update->nodes_count; i++) {
922+
const FlutterSemanticsNode* node = &update->nodes[i];
923+
_bridge->AddFlutterSemanticsNodeUpdate(node);
928924
}
929-
_bridge->AddFlutterSemanticsNodeUpdate(node);
930-
}
931925

932-
- (void)updateSemanticsCustomActions:(const FlutterSemanticsCustomAction*)action {
933-
NSAssert(_bridge, @"The accessibility bridge must be initialized.");
934-
if (action->id == kFlutterSemanticsNodeIdBatchEnd) {
935-
// Custom action with id = kFlutterSemanticsNodeIdBatchEnd indicates this is
936-
// the end of the update batch.
937-
_bridge->CommitUpdates();
938-
// Accessibility tree can only be used when the view is loaded.
939-
if (!self.viewController.viewLoaded) {
940-
return;
941-
}
942-
// Attaches the accessibility root to the flutter view.
943-
auto root = _bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
944-
if (root) {
945-
if ([self.viewController.flutterView.accessibilityChildren count] == 0) {
946-
NSAccessibilityElement* native_root = root->GetNativeViewAccessible();
947-
self.viewController.flutterView.accessibilityChildren = @[ native_root ];
948-
}
949-
} else {
950-
self.viewController.flutterView.accessibilityChildren = nil;
951-
}
926+
for (size_t i = 0; i < update->custom_actions_count; i++) {
927+
const FlutterSemanticsCustomAction* action = &update->custom_actions[i];
928+
_bridge->AddFlutterSemanticsCustomActionUpdate(action);
929+
}
930+
931+
_bridge->CommitUpdates();
932+
933+
// Accessibility tree can only be used when the view is loaded.
934+
if (!self.viewController.viewLoaded) {
952935
return;
953936
}
954-
_bridge->AddFlutterSemanticsCustomActionUpdate(action);
937+
// Attaches the accessibility root to the flutter view.
938+
auto root = _bridge->GetFlutterPlatformNodeDelegateFromID(0).lock();
939+
if (root) {
940+
if ([self.viewController.flutterView.accessibilityChildren count] == 0) {
941+
NSAccessibilityElement* native_root = root->GetNativeViewAccessible();
942+
self.viewController.flutterView.accessibilityChildren = @[ native_root ];
943+
}
944+
} else {
945+
self.viewController.flutterView.accessibilityChildren = nil;
946+
}
955947
}
956948

957949
#pragma mark - Task runner integration

shell/platform/darwin/macos/framework/Source/FlutterEngineTest.mm

Lines changed: 27 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -105,14 +105,12 @@ @interface FlutterEngine (Test)
105105
FlutterEngine* engine = GetFlutterEngine();
106106
// Capture the update callbacks before the embedder API initializes.
107107
auto original_init = engine.embedderAPI.Initialize;
108-
std::function<void(const FlutterSemanticsNode*, void*)> update_node_callback;
109-
std::function<void(const FlutterSemanticsCustomAction*, void*)> update_action_callback;
108+
std::function<void(const FlutterSemanticsUpdate*, void*)> update_semantics_callback;
110109
engine.embedderAPI.Initialize = MOCK_ENGINE_PROC(
111-
Initialize, ([&update_action_callback, &update_node_callback, &original_init](
110+
Initialize, ([&update_semantics_callback, &original_init](
112111
size_t version, const FlutterRendererConfig* config,
113112
const FlutterProjectArgs* args, void* user_data, auto engine_out) {
114-
update_node_callback = args->update_semantics_node_callback;
115-
update_action_callback = args->update_semantics_custom_action_callback;
113+
update_semantics_callback = args->update_semantics_callback;
116114
return original_init(version, config, args, user_data, engine_out);
117115
}));
118116
EXPECT_TRUE([engine runWithEntrypoint:@"main"]);
@@ -150,7 +148,6 @@ @interface FlutterEngine (Test)
150148
int32_t children[] = {1};
151149
root.children_in_traversal_order = children;
152150
root.custom_accessibility_actions_count = 0;
153-
update_node_callback(&root, (void*)CFBridgingRetain(engine));
154151

155152
FlutterSemanticsNode child1;
156153
child1.id = 1;
@@ -166,15 +163,13 @@ @interface FlutterEngine (Test)
166163
child1.tooltip = "";
167164
child1.child_count = 0;
168165
child1.custom_accessibility_actions_count = 0;
169-
update_node_callback(&child1, (void*)CFBridgingRetain(engine));
170166

171-
FlutterSemanticsNode node_batch_end;
172-
node_batch_end.id = kFlutterSemanticsNodeIdBatchEnd;
173-
update_node_callback(&node_batch_end, (void*)CFBridgingRetain(engine));
174-
175-
FlutterSemanticsCustomAction action_batch_end;
176-
action_batch_end.id = kFlutterSemanticsNodeIdBatchEnd;
177-
update_action_callback(&action_batch_end, (void*)CFBridgingRetain(engine));
167+
FlutterSemanticsUpdate update;
168+
update.nodes_count = 2;
169+
FlutterSemanticsNode nodes[] = {root, child1};
170+
update.nodes = nodes;
171+
update.custom_actions_count = 0;
172+
update_semantics_callback(&update, (void*)CFBridgingRetain(engine));
178173

179174
// Verify the accessibility tree is attached to the flutter view.
180175
EXPECT_EQ([engine.viewController.flutterView.accessibilityChildren count], 1u);
@@ -207,14 +202,12 @@ @interface FlutterEngine (Test)
207202
FlutterEngine* engine = GetFlutterEngine();
208203
// Capture the update callbacks before the embedder API initializes.
209204
auto original_init = engine.embedderAPI.Initialize;
210-
std::function<void(const FlutterSemanticsNode*, void*)> update_node_callback;
211-
std::function<void(const FlutterSemanticsCustomAction*, void*)> update_action_callback;
205+
std::function<void(const FlutterSemanticsUpdate*, void*)> update_semantics_callback;
212206
engine.embedderAPI.Initialize = MOCK_ENGINE_PROC(
213-
Initialize, ([&update_action_callback, &update_node_callback, &original_init](
207+
Initialize, ([&update_semantics_callback, &original_init](
214208
size_t version, const FlutterRendererConfig* config,
215209
const FlutterProjectArgs* args, void* user_data, auto engine_out) {
216-
update_node_callback = args->update_semantics_node_callback;
217-
update_action_callback = args->update_semantics_custom_action_callback;
210+
update_semantics_callback = args->update_semantics_callback;
218211
return original_init(version, config, args, user_data, engine_out);
219212
}));
220213
EXPECT_TRUE([engine runWithEntrypoint:@"main"]);
@@ -245,7 +238,6 @@ @interface FlutterEngine (Test)
245238
int32_t children[] = {1};
246239
root.children_in_traversal_order = children;
247240
root.custom_accessibility_actions_count = 0;
248-
update_node_callback(&root, (void*)CFBridgingRetain(engine));
249241

250242
FlutterSemanticsNode child1;
251243
child1.id = 1;
@@ -261,15 +253,13 @@ @interface FlutterEngine (Test)
261253
child1.tooltip = "";
262254
child1.child_count = 0;
263255
child1.custom_accessibility_actions_count = 0;
264-
update_node_callback(&child1, (void*)CFBridgingRetain(engine));
265-
266-
FlutterSemanticsNode node_batch_end;
267-
node_batch_end.id = kFlutterSemanticsNodeIdBatchEnd;
268-
update_node_callback(&node_batch_end, (void*)CFBridgingRetain(engine));
269256

270-
FlutterSemanticsCustomAction action_batch_end;
271-
action_batch_end.id = kFlutterSemanticsNodeIdBatchEnd;
272-
update_action_callback(&action_batch_end, (void*)CFBridgingRetain(engine));
257+
FlutterSemanticsUpdate update;
258+
update.nodes_count = 2;
259+
FlutterSemanticsNode nodes[] = {root, child1};
260+
update.nodes = nodes;
261+
update.custom_actions_count = 0;
262+
update_semantics_callback(&update, (void*)CFBridgingRetain(engine));
273263

274264
// No crashes.
275265
EXPECT_EQ(engine.viewController, nil);
@@ -291,14 +281,12 @@ @interface FlutterEngine (Test)
291281
FlutterEngine* engine = GetFlutterEngine();
292282
// Capture the update callbacks before the embedder API initializes.
293283
auto original_init = engine.embedderAPI.Initialize;
294-
std::function<void(const FlutterSemanticsNode*, void*)> update_node_callback;
295-
std::function<void(const FlutterSemanticsCustomAction*, void*)> update_action_callback;
284+
std::function<void(const FlutterSemanticsUpdate*, void*)> update_semantics_callback;
296285
engine.embedderAPI.Initialize = MOCK_ENGINE_PROC(
297-
Initialize, ([&update_action_callback, &update_node_callback, &original_init](
286+
Initialize, ([&update_semantics_callback, &original_init](
298287
size_t version, const FlutterRendererConfig* config,
299288
const FlutterProjectArgs* args, void* user_data, auto engine_out) {
300-
update_node_callback = args->update_semantics_node_callback;
301-
update_action_callback = args->update_semantics_custom_action_callback;
289+
update_semantics_callback = args->update_semantics_callback;
302290
return original_init(version, config, args, user_data, engine_out);
303291
}));
304292
EXPECT_TRUE([engine runWithEntrypoint:@"main"]);
@@ -336,7 +324,6 @@ @interface FlutterEngine (Test)
336324
int32_t children[] = {1};
337325
root.children_in_traversal_order = children;
338326
root.custom_accessibility_actions_count = 0;
339-
update_node_callback(&root, (void*)CFBridgingRetain(engine));
340327

341328
FlutterSemanticsNode child1;
342329
child1.id = 1;
@@ -352,15 +339,13 @@ @interface FlutterEngine (Test)
352339
child1.tooltip = "";
353340
child1.child_count = 0;
354341
child1.custom_accessibility_actions_count = 0;
355-
update_node_callback(&child1, (void*)CFBridgingRetain(engine));
356-
357-
FlutterSemanticsNode node_batch_end;
358-
node_batch_end.id = kFlutterSemanticsNodeIdBatchEnd;
359-
update_node_callback(&node_batch_end, (void*)CFBridgingRetain(engine));
360342

361-
FlutterSemanticsCustomAction action_batch_end;
362-
action_batch_end.id = kFlutterSemanticsNodeIdBatchEnd;
363-
update_action_callback(&action_batch_end, (void*)CFBridgingRetain(engine));
343+
FlutterSemanticsUpdate update;
344+
update.nodes_count = 2;
345+
FlutterSemanticsNode nodes[] = {root, child1};
346+
update.nodes = nodes;
347+
update.custom_actions_count = 0;
348+
update_semantics_callback(&update, (void*)CFBridgingRetain(engine));
364349

365350
auto native_root = engine.accessibilityBridge.lock()->GetFlutterPlatformNodeDelegateFromID(0);
366351
EXPECT_FALSE(native_root.expired());

0 commit comments

Comments
 (0)