@@ -1268,10 +1268,10 @@ FlutterSemanticsNode CreateEmbedderSemanticsNode(
1268
1268
transform.get (SkMatrix::kMScaleY ), transform.get (SkMatrix::kMTransY ),
1269
1269
transform.get (SkMatrix::kMPersp0 ), transform.get (SkMatrix::kMPersp1 ),
1270
1270
transform.get (SkMatrix::kMPersp2 )};
1271
+
1271
1272
// Do not add new members to FlutterSemanticsNode.
1272
1273
// This would break the forward compatibility of FlutterSemanticsUpdate.
1273
- // TODO(loicsharma): Introduce FlutterSemanticsNode2.
1274
- // https://github.com/flutter/flutter/issues/121176
1274
+ // All new members must be added to FlutterSemanticsNode2 instead.
1275
1275
return {
1276
1276
sizeof (FlutterSemanticsNode),
1277
1277
node.id ,
@@ -1305,14 +1305,56 @@ FlutterSemanticsNode CreateEmbedderSemanticsNode(
1305
1305
};
1306
1306
}
1307
1307
1308
+ // Translates engine semantic nodes to embedder semantic nodes.
1309
+ FlutterSemanticsNode2 CreateEmbedderSemanticsNode2 (
1310
+ const flutter::SemanticsNode& node) {
1311
+ SkMatrix transform = node.transform .asM33 ();
1312
+ FlutterTransformation flutter_transform{
1313
+ transform.get (SkMatrix::kMScaleX ), transform.get (SkMatrix::kMSkewX ),
1314
+ transform.get (SkMatrix::kMTransX ), transform.get (SkMatrix::kMSkewY ),
1315
+ transform.get (SkMatrix::kMScaleY ), transform.get (SkMatrix::kMTransY ),
1316
+ transform.get (SkMatrix::kMPersp0 ), transform.get (SkMatrix::kMPersp1 ),
1317
+ transform.get (SkMatrix::kMPersp2 )};
1318
+ return {
1319
+ sizeof (FlutterSemanticsNode2),
1320
+ node.id ,
1321
+ static_cast <FlutterSemanticsFlag>(node.flags ),
1322
+ static_cast <FlutterSemanticsAction>(node.actions ),
1323
+ node.textSelectionBase ,
1324
+ node.textSelectionExtent ,
1325
+ node.scrollChildren ,
1326
+ node.scrollIndex ,
1327
+ node.scrollPosition ,
1328
+ node.scrollExtentMax ,
1329
+ node.scrollExtentMin ,
1330
+ node.elevation ,
1331
+ node.thickness ,
1332
+ node.label .c_str (),
1333
+ node.hint .c_str (),
1334
+ node.value .c_str (),
1335
+ node.increasedValue .c_str (),
1336
+ node.decreasedValue .c_str (),
1337
+ static_cast <FlutterTextDirection>(node.textDirection ),
1338
+ FlutterRect{node.rect .fLeft , node.rect .fTop , node.rect .fRight ,
1339
+ node.rect .fBottom },
1340
+ flutter_transform,
1341
+ node.childrenInTraversalOrder .size (),
1342
+ node.childrenInTraversalOrder .data (),
1343
+ node.childrenInHitTestOrder .data (),
1344
+ node.customAccessibilityActions .size (),
1345
+ node.customAccessibilityActions .data (),
1346
+ node.platformViewId ,
1347
+ node.tooltip .c_str (),
1348
+ };
1349
+ }
1350
+
1308
1351
// Translates engine semantic custom actions to embedder semantic custom
1309
1352
// actions.
1310
1353
FlutterSemanticsCustomAction CreateEmbedderSemanticsCustomAction (
1311
1354
const flutter::CustomAccessibilityAction& action) {
1312
1355
// Do not add new members to FlutterSemanticsCustomAction.
1313
1356
// This would break the forward compatibility of FlutterSemanticsUpdate.
1314
- // TODO(loicsharma): Introduce FlutterSemanticsCustomAction2.
1315
- // https://github.com/flutter/flutter/issues/121176
1357
+ // All new members must be added to FlutterSemanticsCustomAction2 instead.
1316
1358
return {
1317
1359
sizeof (FlutterSemanticsCustomAction),
1318
1360
action.id ,
@@ -1322,8 +1364,21 @@ FlutterSemanticsCustomAction CreateEmbedderSemanticsCustomAction(
1322
1364
};
1323
1365
}
1324
1366
1367
+ // Translates engine semantic custom actions to embedder semantic custom
1368
+ // actions.
1369
+ FlutterSemanticsCustomAction2 CreateEmbedderSemanticsCustomAction2 (
1370
+ const flutter::CustomAccessibilityAction& action) {
1371
+ return {
1372
+ sizeof (FlutterSemanticsCustomAction2),
1373
+ action.id ,
1374
+ static_cast <FlutterSemanticsAction>(action.overrideId ),
1375
+ action.label .c_str (),
1376
+ action.hint .c_str (),
1377
+ };
1378
+ }
1379
+
1325
1380
// Create a callback to notify the embedder of semantic updates
1326
- // using the new embedder callback 'update_semantics_callback'.
1381
+ // using the deprecated embedder callback 'update_semantics_callback'.
1327
1382
flutter::PlatformViewEmbedder::UpdateSemanticsCallback
1328
1383
CreateNewEmbedderSemanticsUpdateCallback (
1329
1384
FlutterUpdateSemanticsCallback update_semantics_callback,
@@ -1354,6 +1409,58 @@ CreateNewEmbedderSemanticsUpdateCallback(
1354
1409
};
1355
1410
}
1356
1411
1412
+ // Create a callback to notify the embedder of semantic updates
1413
+ // using the new embedder callback 'update_semantics_callback2'.
1414
+ flutter::PlatformViewEmbedder::UpdateSemanticsCallback
1415
+ CreateNewEmbedderSemanticsUpdateCallback2 (
1416
+ FlutterUpdateSemanticsCallback2 update_semantics_callback,
1417
+ void * user_data) {
1418
+ return [update_semantics_callback, user_data](
1419
+ const flutter::SemanticsNodeUpdates& nodes,
1420
+ const flutter::CustomAccessibilityActionUpdates& actions) {
1421
+ std::vector<FlutterSemanticsNode2> embedder_nodes;
1422
+ std::vector<FlutterSemanticsCustomAction2> embedder_custom_actions;
1423
+
1424
+ embedder_nodes.reserve (nodes.size ());
1425
+ embedder_custom_actions.reserve (actions.size ());
1426
+
1427
+ for (const auto & value : nodes) {
1428
+ embedder_nodes.push_back (CreateEmbedderSemanticsNode2 (value.second ));
1429
+ }
1430
+
1431
+ for (const auto & value : actions) {
1432
+ embedder_custom_actions.push_back (
1433
+ CreateEmbedderSemanticsCustomAction2 (value.second ));
1434
+ }
1435
+
1436
+ // Provide the embedder an array of pointers to maintain full forward and
1437
+ // backward compatibility even if new members are added to semantic structs.
1438
+ std::vector<FlutterSemanticsNode2*> embedder_node_pointers;
1439
+ std::vector<FlutterSemanticsCustomAction2*> embedder_custom_action_pointers;
1440
+
1441
+ embedder_node_pointers.reserve (embedder_nodes.size ());
1442
+ embedder_custom_action_pointers.reserve (embedder_custom_actions.size ());
1443
+
1444
+ for (auto & node : embedder_nodes) {
1445
+ embedder_node_pointers.push_back (&node);
1446
+ }
1447
+
1448
+ for (auto & action : embedder_custom_actions) {
1449
+ embedder_custom_action_pointers.push_back (&action);
1450
+ }
1451
+
1452
+ FlutterSemanticsUpdate2 update{
1453
+ .struct_size = sizeof (FlutterSemanticsUpdate2),
1454
+ .node_count = embedder_node_pointers.size (),
1455
+ .nodes = embedder_node_pointers.data (),
1456
+ .custom_action_count = embedder_custom_action_pointers.size (),
1457
+ .custom_actions = embedder_custom_action_pointers.data (),
1458
+ };
1459
+
1460
+ update_semantics_callback (&update, user_data);
1461
+ };
1462
+ }
1463
+
1357
1464
// Create a callback to notify the embedder of semantic updates
1358
1465
// using the legacy embedder callbacks 'update_semantics_node_callback' and
1359
1466
// 'update_semantics_custom_action_callback'.
@@ -1413,6 +1520,11 @@ CreateEmbedderSemanticsUpdateCallback(const FlutterProjectArgs* args,
1413
1520
// The embedder can register the new callback, or the legacy callbacks, or
1414
1521
// nothing at all. Handle the case where the embedder registered the 'new'
1415
1522
// callback.
1523
+ if (SAFE_ACCESS (args, update_semantics_callback2, nullptr ) != nullptr ) {
1524
+ return CreateNewEmbedderSemanticsUpdateCallback2 (
1525
+ args->update_semantics_callback2 , user_data);
1526
+ }
1527
+
1416
1528
if (SAFE_ACCESS (args, update_semantics_callback, nullptr ) != nullptr ) {
1417
1529
return CreateNewEmbedderSemanticsUpdateCallback (
1418
1530
args->update_semantics_callback , user_data);
@@ -1590,15 +1702,27 @@ FlutterEngineResult FlutterEngineInitialize(size_t version,
1590
1702
settings.log_tag = SAFE_ACCESS (args, log_tag, nullptr );
1591
1703
}
1592
1704
1593
- if (args->update_semantics_callback != nullptr &&
1594
- (args->update_semantics_node_callback != nullptr ||
1595
- args->update_semantics_custom_action_callback != nullptr )) {
1705
+ bool has_update_semantics_2_callback =
1706
+ SAFE_ACCESS (args, update_semantics_callback2, nullptr ) != nullptr ;
1707
+ bool has_update_semantics_callback =
1708
+ SAFE_ACCESS (args, update_semantics_callback, nullptr ) != nullptr ;
1709
+ bool has_legacy_update_semantics_callback =
1710
+ SAFE_ACCESS (args, update_semantics_node_callback, nullptr ) != nullptr ||
1711
+ SAFE_ACCESS (args, update_semantics_custom_action_callback, nullptr ) !=
1712
+ nullptr ;
1713
+
1714
+ int semantic_callback_count = (has_update_semantics_2_callback ? 1 : 0 ) +
1715
+ (has_update_semantics_callback ? 1 : 0 ) +
1716
+ (has_legacy_update_semantics_callback ? 1 : 0 );
1717
+
1718
+ if (semantic_callback_count > 1 ) {
1596
1719
return LOG_EMBEDDER_ERROR (
1597
1720
kInvalidArguments ,
1598
1721
" Multiple semantics update callbacks provided. "
1599
- " Embedders should provide either `update_semantics_callback` "
1600
- " or both `update_semantics_nodes_callback` and "
1601
- " `update_semantics_custom_actions_callback`." );
1722
+ " Embedders should provide either `update_semantics_callback2`, "
1723
+ " `update_semantics_callback`, or both "
1724
+ " `update_semantics_node_callback` and "
1725
+ " `update_semantics_custom_action_callback`." );
1602
1726
}
1603
1727
1604
1728
flutter::PlatformViewEmbedder::UpdateSemanticsCallback
0 commit comments