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

Commit 0d4bcd8

Browse files
committed
[macOS] Move to new update semantics embedder API
1 parent 8aefb8b commit 0d4bcd8

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
@@ -307,16 +307,11 @@ - (BOOL)runWithEntrypoint:(NSString*)entrypoint {
307307
flutterArguments.command_line_argc = static_cast<int>(argv.size());
308308
flutterArguments.command_line_argv = argv.empty() ? nullptr : argv.data();
309309
flutterArguments.platform_message_callback = (FlutterPlatformMessageCallback)OnPlatformMessage;
310-
flutterArguments.update_semantics_node_callback = [](const FlutterSemanticsNode* node,
311-
void* user_data) {
310+
flutterArguments.update_semantics_callback = [](const FlutterSemanticsUpdate* update,
311+
void* user_data) {
312312
FlutterEngine* engine = (__bridge FlutterEngine*)user_data;
313-
[engine updateSemanticsNode:node];
313+
[engine updateSemantics:update];
314314
};
315-
flutterArguments.update_semantics_custom_action_callback =
316-
[](const FlutterSemanticsCustomAction* action, void* user_data) {
317-
FlutterEngine* engine = (__bridge FlutterEngine*)user_data;
318-
[engine updateSemanticsCustomActions:action];
319-
};
320315
flutterArguments.custom_dart_entrypoint = entrypoint.UTF8String;
321316
flutterArguments.shutdown_dart_vm_when_done = true;
322317
flutterArguments.dart_entrypoint_argc = dartEntrypointArgs.size();
@@ -928,37 +923,34 @@ - (BOOL)unregisterTextureWithID:(int64_t)textureID {
928923
return _embedderAPI.UnregisterExternalTexture(_engine, textureID) == kSuccess;
929924
}
930925

931-
- (void)updateSemanticsNode:(const FlutterSemanticsNode*)node {
926+
- (void)updateSemantics:(const FlutterSemanticsUpdate*)update {
932927
NSAssert(_bridge, @"The accessibility bridge must be initialized.");
933-
if (node->id == kFlutterSemanticsNodeIdBatchEnd) {
934-
return;
928+
for (size_t i = 0; i < update->nodes_count; i++) {
929+
const FlutterSemanticsNode* node = &update->nodes[i];
930+
_bridge->AddFlutterSemanticsNodeUpdate(node);
935931
}
936-
_bridge->AddFlutterSemanticsNodeUpdate(node);
937-
}
938932

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

964956
#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
@@ -166,14 +166,12 @@ @interface FlutterEngine (Test)
166166
FlutterEngine* engine = GetFlutterEngine();
167167
// Capture the update callbacks before the embedder API initializes.
168168
auto original_init = engine.embedderAPI.Initialize;
169-
std::function<void(const FlutterSemanticsNode*, void*)> update_node_callback;
170-
std::function<void(const FlutterSemanticsCustomAction*, void*)> update_action_callback;
169+
std::function<void(const FlutterSemanticsUpdate*, void*)> update_semantics_callback;
171170
engine.embedderAPI.Initialize = MOCK_ENGINE_PROC(
172-
Initialize, ([&update_action_callback, &update_node_callback, &original_init](
171+
Initialize, ([&update_semantics_callback, &original_init](
173172
size_t version, const FlutterRendererConfig* config,
174173
const FlutterProjectArgs* args, void* user_data, auto engine_out) {
175-
update_node_callback = args->update_semantics_node_callback;
176-
update_action_callback = args->update_semantics_custom_action_callback;
174+
update_semantics_callback = args->update_semantics_callback;
177175
return original_init(version, config, args, user_data, engine_out);
178176
}));
179177
EXPECT_TRUE([engine runWithEntrypoint:@"main"]);
@@ -211,7 +209,6 @@ @interface FlutterEngine (Test)
211209
int32_t children[] = {1};
212210
root.children_in_traversal_order = children;
213211
root.custom_accessibility_actions_count = 0;
214-
update_node_callback(&root, (void*)CFBridgingRetain(engine));
215212

216213
FlutterSemanticsNode child1;
217214
child1.id = 1;
@@ -227,15 +224,13 @@ @interface FlutterEngine (Test)
227224
child1.tooltip = "";
228225
child1.child_count = 0;
229226
child1.custom_accessibility_actions_count = 0;
230-
update_node_callback(&child1, (void*)CFBridgingRetain(engine));
231227

232-
FlutterSemanticsNode node_batch_end;
233-
node_batch_end.id = kFlutterSemanticsNodeIdBatchEnd;
234-
update_node_callback(&node_batch_end, (void*)CFBridgingRetain(engine));
235-
236-
FlutterSemanticsCustomAction action_batch_end;
237-
action_batch_end.id = kFlutterSemanticsNodeIdBatchEnd;
238-
update_action_callback(&action_batch_end, (void*)CFBridgingRetain(engine));
228+
FlutterSemanticsUpdate update;
229+
update.nodes_count = 2;
230+
FlutterSemanticsNode nodes[] = {root, child1};
231+
update.nodes = nodes;
232+
update.custom_actions_count = 0;
233+
update_semantics_callback(&update, (void*)CFBridgingRetain(engine));
239234

240235
// Verify the accessibility tree is attached to the flutter view.
241236
EXPECT_EQ([engine.viewController.flutterView.accessibilityChildren count], 1u);
@@ -268,14 +263,12 @@ @interface FlutterEngine (Test)
268263
FlutterEngine* engine = GetFlutterEngine();
269264
// Capture the update callbacks before the embedder API initializes.
270265
auto original_init = engine.embedderAPI.Initialize;
271-
std::function<void(const FlutterSemanticsNode*, void*)> update_node_callback;
272-
std::function<void(const FlutterSemanticsCustomAction*, void*)> update_action_callback;
266+
std::function<void(const FlutterSemanticsUpdate*, void*)> update_semantics_callback;
273267
engine.embedderAPI.Initialize = MOCK_ENGINE_PROC(
274-
Initialize, ([&update_action_callback, &update_node_callback, &original_init](
268+
Initialize, ([&update_semantics_callback, &original_init](
275269
size_t version, const FlutterRendererConfig* config,
276270
const FlutterProjectArgs* args, void* user_data, auto engine_out) {
277-
update_node_callback = args->update_semantics_node_callback;
278-
update_action_callback = args->update_semantics_custom_action_callback;
271+
update_semantics_callback = args->update_semantics_callback;
279272
return original_init(version, config, args, user_data, engine_out);
280273
}));
281274
EXPECT_TRUE([engine runWithEntrypoint:@"main"]);
@@ -306,7 +299,6 @@ @interface FlutterEngine (Test)
306299
int32_t children[] = {1};
307300
root.children_in_traversal_order = children;
308301
root.custom_accessibility_actions_count = 0;
309-
update_node_callback(&root, (void*)CFBridgingRetain(engine));
310302

311303
FlutterSemanticsNode child1;
312304
child1.id = 1;
@@ -322,15 +314,13 @@ @interface FlutterEngine (Test)
322314
child1.tooltip = "";
323315
child1.child_count = 0;
324316
child1.custom_accessibility_actions_count = 0;
325-
update_node_callback(&child1, (void*)CFBridgingRetain(engine));
326-
327-
FlutterSemanticsNode node_batch_end;
328-
node_batch_end.id = kFlutterSemanticsNodeIdBatchEnd;
329-
update_node_callback(&node_batch_end, (void*)CFBridgingRetain(engine));
330317

331-
FlutterSemanticsCustomAction action_batch_end;
332-
action_batch_end.id = kFlutterSemanticsNodeIdBatchEnd;
333-
update_action_callback(&action_batch_end, (void*)CFBridgingRetain(engine));
318+
FlutterSemanticsUpdate update;
319+
update.nodes_count = 2;
320+
FlutterSemanticsNode nodes[] = {root, child1};
321+
update.nodes = nodes;
322+
update.custom_actions_count = 0;
323+
update_semantics_callback(&update, (void*)CFBridgingRetain(engine));
334324

335325
// No crashes.
336326
EXPECT_EQ(engine.viewController, nil);
@@ -352,14 +342,12 @@ @interface FlutterEngine (Test)
352342
FlutterEngine* engine = GetFlutterEngine();
353343
// Capture the update callbacks before the embedder API initializes.
354344
auto original_init = engine.embedderAPI.Initialize;
355-
std::function<void(const FlutterSemanticsNode*, void*)> update_node_callback;
356-
std::function<void(const FlutterSemanticsCustomAction*, void*)> update_action_callback;
345+
std::function<void(const FlutterSemanticsUpdate*, void*)> update_semantics_callback;
357346
engine.embedderAPI.Initialize = MOCK_ENGINE_PROC(
358-
Initialize, ([&update_action_callback, &update_node_callback, &original_init](
347+
Initialize, ([&update_semantics_callback, &original_init](
359348
size_t version, const FlutterRendererConfig* config,
360349
const FlutterProjectArgs* args, void* user_data, auto engine_out) {
361-
update_node_callback = args->update_semantics_node_callback;
362-
update_action_callback = args->update_semantics_custom_action_callback;
350+
update_semantics_callback = args->update_semantics_callback;
363351
return original_init(version, config, args, user_data, engine_out);
364352
}));
365353
EXPECT_TRUE([engine runWithEntrypoint:@"main"]);
@@ -397,7 +385,6 @@ @interface FlutterEngine (Test)
397385
int32_t children[] = {1};
398386
root.children_in_traversal_order = children;
399387
root.custom_accessibility_actions_count = 0;
400-
update_node_callback(&root, (void*)CFBridgingRetain(engine));
401388

402389
FlutterSemanticsNode child1;
403390
child1.id = 1;
@@ -413,15 +400,13 @@ @interface FlutterEngine (Test)
413400
child1.tooltip = "";
414401
child1.child_count = 0;
415402
child1.custom_accessibility_actions_count = 0;
416-
update_node_callback(&child1, (void*)CFBridgingRetain(engine));
417-
418-
FlutterSemanticsNode node_batch_end;
419-
node_batch_end.id = kFlutterSemanticsNodeIdBatchEnd;
420-
update_node_callback(&node_batch_end, (void*)CFBridgingRetain(engine));
421403

422-
FlutterSemanticsCustomAction action_batch_end;
423-
action_batch_end.id = kFlutterSemanticsNodeIdBatchEnd;
424-
update_action_callback(&action_batch_end, (void*)CFBridgingRetain(engine));
404+
FlutterSemanticsUpdate update;
405+
update.nodes_count = 2;
406+
FlutterSemanticsNode nodes[] = {root, child1};
407+
update.nodes = nodes;
408+
update.custom_actions_count = 0;
409+
update_semantics_callback(&update, (void*)CFBridgingRetain(engine));
425410

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

0 commit comments

Comments
 (0)