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

Commit aa14377

Browse files
committed
Apply dpr transform to fuchsia accessibility bridge
1 parent 876d634 commit aa14377

File tree

5 files changed

+111
-15
lines changed

5 files changed

+111
-15
lines changed

shell/platform/fuchsia/flutter/accessibility_bridge.cc

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,14 @@ fuchsia::ui::gfx::BoundingBox AccessibilityBridge::GetNodeLocation(
5656

5757
fuchsia::ui::gfx::mat4 AccessibilityBridge::GetNodeTransform(
5858
const flutter::SemanticsNode& node) const {
59+
return ConvertSkiaTransformToMat4(node.transform);
60+
}
61+
62+
fuchsia::ui::gfx::mat4 AccessibilityBridge::ConvertSkiaTransformToMat4(
63+
const SkM44 transform) const {
5964
fuchsia::ui::gfx::mat4 value;
6065
float* m = value.matrix.data();
61-
node.transform.getColMajor(m);
66+
transform.getColMajor(m);
6267
return value;
6368
}
6469

@@ -259,6 +264,13 @@ void AccessibilityBridge::AddSemanticsNodeUpdate(
259264
for (const auto& value : update) {
260265
size_t this_node_size = sizeof(fuchsia::accessibility::semantics::Node);
261266
const auto& flutter_node = value.second;
267+
// We handle root update separately in GetRootNodeUpdate.
268+
// TODO(chunhtai): remove this special case after we remove the inverse
269+
// view pixel ratio transformation in scenic view.
270+
if (flutter_node.id == kRootNodeId) {
271+
root_flutter_semantics_node_ = flutter_node;
272+
continue;
273+
}
262274
// Store the nodes for later hit testing.
263275
nodes_[flutter_node.id] = {
264276
.id = flutter_node.id,
@@ -292,7 +304,6 @@ void AccessibilityBridge::AddSemanticsNodeUpdate(
292304
PrintNodeSizeError(flutter_node.id);
293305
return;
294306
}
295-
296307
current_size += this_node_size;
297308

298309
// If we would exceed the max FIDL message size by appending this node,
@@ -309,15 +320,62 @@ void AccessibilityBridge::AddSemanticsNodeUpdate(
309320
PrintNodeSizeError(nodes.back().node_id());
310321
}
311322

323+
// Even if the SemanticsNodeUpdates does not contain the root node, we still
324+
// need to generate an update for the root node in case the view pixel ratio
325+
// has changed.
326+
std::vector<fuchsia::accessibility::semantics::Node> root_update;
327+
root_update.push_back(GetRootNodeUpdate());
328+
312329
PruneUnreachableNodes();
313330
UpdateScreenRects();
314331

315-
tree_ptr_->UpdateSemanticNodes(std::move(nodes));
332+
tree_ptr_->UpdateSemanticNodes(std::move(root_update));
333+
if (!nodes.empty())
334+
tree_ptr_->UpdateSemanticNodes(std::move(nodes));
316335
// TODO(dnfield): Implement the callback here
317336
// https://bugs.fuchsia.dev/p/fuchsia/issues/detail?id=35718.
318337
tree_ptr_->CommitUpdates([]() {});
319338
}
320339

340+
fuchsia::accessibility::semantics::Node
341+
AccessibilityBridge::GetRootNodeUpdate() {
342+
fuchsia::accessibility::semantics::Node root_fuchsia_node;
343+
std::vector<uint32_t> child_ids;
344+
size_t this_node_size = sizeof(fuchsia::accessibility::semantics::Node);
345+
for (int32_t flutter_child_id :
346+
root_flutter_semantics_node_.childrenInTraversalOrder) {
347+
child_ids.push_back(FlutterIdToFuchsiaId(flutter_child_id));
348+
}
349+
// Applies the inverse view pixel ratio transformation to the root node.
350+
float view_pixel_ratio = delegate_.GetViewPixelRatio();
351+
float inverse_view_pixel_ratio = 1.f / view_pixel_ratio;
352+
SkM44 inverse_view_pixel_ratio_transform;
353+
inverse_view_pixel_ratio_transform.setScale(inverse_view_pixel_ratio,
354+
inverse_view_pixel_ratio, 1.f);
355+
356+
SkM44 result = root_flutter_semantics_node_.transform *
357+
inverse_view_pixel_ratio_transform;
358+
nodes_[root_flutter_semantics_node_.id] = {
359+
.id = root_flutter_semantics_node_.id,
360+
.flags = root_flutter_semantics_node_.flags,
361+
.rect = root_flutter_semantics_node_.rect,
362+
.transform = result,
363+
.children_in_hit_test_order =
364+
root_flutter_semantics_node_.childrenInHitTestOrder,
365+
};
366+
root_fuchsia_node.set_node_id(root_flutter_semantics_node_.id)
367+
.set_role(GetNodeRole(root_flutter_semantics_node_))
368+
.set_location(GetNodeLocation(root_flutter_semantics_node_))
369+
.set_transform(ConvertSkiaTransformToMat4(result))
370+
.set_attributes(
371+
GetNodeAttributes(root_flutter_semantics_node_, &this_node_size))
372+
.set_states(GetNodeStates(root_flutter_semantics_node_, &this_node_size))
373+
.set_actions(
374+
GetNodeActions(root_flutter_semantics_node_, &this_node_size))
375+
.set_child_ids(child_ids);
376+
return root_fuchsia_node;
377+
}
378+
321379
void AccessibilityBridge::UpdateScreenRects() {
322380
std::unordered_set<int32_t> visited_nodes;
323381
UpdateScreenRects(kRootNodeId, SkM44{}, &visited_nodes);

shell/platform/fuchsia/flutter/accessibility_bridge.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ class AccessibilityBridge
4646
virtual void SetSemanticsEnabled(bool enabled) = 0;
4747
virtual void DispatchSemanticsAction(int32_t node_id,
4848
flutter::SemanticsAction action) = 0;
49+
virtual float GetViewPixelRatio() = 0;
4950
};
5051

5152
// TODO(MI4-2531, FIDL-718): Remove this. We shouldn't be worried about
@@ -115,6 +116,7 @@ class AccessibilityBridge
115116
AccessibilityBridge::Delegate& delegate_;
116117

117118
static constexpr int32_t kRootNodeId = 0;
119+
flutter::SemanticsNode root_flutter_semantics_node_;
118120
fidl::Binding<fuchsia::accessibility::semantics::SemanticListener> binding_;
119121
fuchsia::accessibility::semantics::SemanticsManagerPtr
120122
fuchsia_semantics_manager_;
@@ -124,15 +126,21 @@ class AccessibilityBridge
124126
// Assists with pruning unreachable nodes and hit testing.
125127
std::unordered_map<int32_t, SemanticsNode> nodes_;
126128

129+
fuchsia::accessibility::semantics::Node GetRootNodeUpdate();
130+
127131
// Derives the BoundingBox of a Flutter semantics node from its
128132
// rect and elevation.
129133
fuchsia::ui::gfx::BoundingBox GetNodeLocation(
130134
const flutter::SemanticsNode& node) const;
131135

132-
// Converts a Flutter semantics node's transformation to a mat4.
136+
// Gets mat4 transformation from a Flutter semantics node.
133137
fuchsia::ui::gfx::mat4 GetNodeTransform(
134138
const flutter::SemanticsNode& node) const;
135139

140+
// Converts a Flutter semantics node's transformation to a mat4.
141+
fuchsia::ui::gfx::mat4 ConvertSkiaTransformToMat4(
142+
const SkM44 transform) const;
143+
136144
// Derives the attributes for a Fuchsia semantics node from a Flutter
137145
// semantics node.
138146
fuchsia::accessibility::semantics::Attributes GetNodeAttributes(

shell/platform/fuchsia/flutter/accessibility_bridge_unittest.cc

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,13 @@ namespace flutter_runner_test {
2222
class AccessibilityBridgeTestDelegate
2323
: public flutter_runner::AccessibilityBridge::Delegate {
2424
public:
25+
float view_pixel_ratio = 1.f;
2526
void SetSemanticsEnabled(bool enabled) override { enabled_ = enabled; }
2627
void DispatchSemanticsAction(int32_t node_id,
2728
flutter::SemanticsAction action) override {
2829
actions.push_back(std::make_pair(node_id, action));
2930
}
31+
float GetViewPixelRatio() override { return view_pixel_ratio; }
3032

3133
bool enabled() { return enabled_; }
3234
std::vector<std::pair<int32_t, flutter::SemanticsAction>> actions;
@@ -112,9 +114,10 @@ TEST_F(AccessibilityBridgeTest, DeletesChildrenTransitively) {
112114
RunLoopUntilIdle();
113115

114116
EXPECT_EQ(0, semantics_manager_.DeleteCount());
115-
EXPECT_EQ(1, semantics_manager_.UpdateCount());
117+
EXPECT_EQ(2, semantics_manager_.UpdateCount());
116118
EXPECT_EQ(1, semantics_manager_.CommitCount());
117-
EXPECT_EQ(3U, semantics_manager_.LastUpdatedNodes().size());
119+
// The root node is in the first update.
120+
EXPECT_EQ(2U, semantics_manager_.LastUpdatedNodes().size());
118121
EXPECT_EQ(0U, semantics_manager_.LastDeletedNodeIds().size());
119122
EXPECT_FALSE(semantics_manager_.DeleteOverflowed());
120123
EXPECT_FALSE(semantics_manager_.UpdateOverflowed());
@@ -128,7 +131,7 @@ TEST_F(AccessibilityBridgeTest, DeletesChildrenTransitively) {
128131
RunLoopUntilIdle();
129132

130133
EXPECT_EQ(1, semantics_manager_.DeleteCount());
131-
EXPECT_EQ(2, semantics_manager_.UpdateCount());
134+
EXPECT_EQ(3, semantics_manager_.UpdateCount());
132135
EXPECT_EQ(2, semantics_manager_.CommitCount());
133136
EXPECT_EQ(1U, semantics_manager_.LastUpdatedNodes().size());
134137
ASSERT_EQ(std::vector<uint32_t>({1, 2}),
@@ -269,6 +272,21 @@ TEST_F(AccessibilityBridgeTest, PopulatesSelectedState) {
269272
EXPECT_FALSE(semantics_manager_.UpdateOverflowed());
270273
}
271274

275+
TEST_F(AccessibilityBridgeTest, ApplyViewPixelRatioToRoot) {
276+
accessibility_delegate_.view_pixel_ratio = 1.25f;
277+
flutter::SemanticsNode node0;
278+
node0.id = 0;
279+
node0.flags = static_cast<int>(flutter::SemanticsFlags::kIsSelected);
280+
281+
accessibility_bridge_->AddSemanticsNodeUpdate({{0, node0}});
282+
RunLoopUntilIdle();
283+
const auto& fuchsia_node = semantics_manager_.LastUpdatedNodes().at(0u);
284+
EXPECT_EQ(fuchsia_node.node_id(), static_cast<unsigned int>(node0.id));
285+
EXPECT_EQ(fuchsia_node.transform().matrix[0], 0.8f);
286+
EXPECT_EQ(fuchsia_node.transform().matrix[5], 0.8f);
287+
EXPECT_EQ(fuchsia_node.transform().matrix[10], 1.f);
288+
}
289+
272290
TEST_F(AccessibilityBridgeTest, PopulatesHiddenState) {
273291
flutter::SemanticsNode node0;
274292
node0.id = 0;
@@ -356,9 +374,10 @@ TEST_F(AccessibilityBridgeTest, TruncatesLargeLabel) {
356374

357375
// Nothing to delete, but we should have broken
358376
EXPECT_EQ(0, semantics_manager_.DeleteCount());
359-
EXPECT_EQ(1, semantics_manager_.UpdateCount());
377+
EXPECT_EQ(2, semantics_manager_.UpdateCount());
360378
EXPECT_EQ(1, semantics_manager_.CommitCount());
361-
EXPECT_EQ(3U, semantics_manager_.LastUpdatedNodes().size());
379+
// The root node is in the first update.
380+
EXPECT_EQ(2U, semantics_manager_.LastUpdatedNodes().size());
362381
auto trimmed_node =
363382
std::find_if(semantics_manager_.LastUpdatedNodes().begin(),
364383
semantics_manager_.LastUpdatedNodes().end(),
@@ -399,9 +418,10 @@ TEST_F(AccessibilityBridgeTest, TruncatesLargeValue) {
399418
RunLoopUntilIdle();
400419

401420
EXPECT_EQ(0, semantics_manager_.DeleteCount());
402-
EXPECT_EQ(1, semantics_manager_.UpdateCount());
421+
EXPECT_EQ(2, semantics_manager_.UpdateCount());
403422
EXPECT_EQ(1, semantics_manager_.CommitCount());
404-
EXPECT_EQ(3U, semantics_manager_.LastUpdatedNodes().size());
423+
// The root node is in the first update.
424+
EXPECT_EQ(2U, semantics_manager_.LastUpdatedNodes().size());
405425
auto trimmed_node =
406426
std::find_if(semantics_manager_.LastUpdatedNodes().begin(),
407427
semantics_manager_.LastUpdatedNodes().end(),
@@ -455,11 +475,12 @@ TEST_F(AccessibilityBridgeTest, SplitsLargeUpdates) {
455475
});
456476
RunLoopUntilIdle();
457477

458-
// Nothing to delete, but we should have broken into groups (4, 3, 2), (1, 0)
478+
// Nothing to delete, but we should have broken into groups (4, 3, 2), (0)
479+
// (1)
459480
EXPECT_EQ(0, semantics_manager_.DeleteCount());
460-
EXPECT_EQ(2, semantics_manager_.UpdateCount());
481+
EXPECT_EQ(3, semantics_manager_.UpdateCount());
461482
EXPECT_EQ(1, semantics_manager_.CommitCount());
462-
EXPECT_EQ(2U, semantics_manager_.LastUpdatedNodes().size());
483+
EXPECT_EQ(1U, semantics_manager_.LastUpdatedNodes().size());
463484
EXPECT_FALSE(semantics_manager_.DeleteOverflowed());
464485
EXPECT_FALSE(semantics_manager_.UpdateOverflowed());
465486
}
@@ -494,7 +515,8 @@ TEST_F(AccessibilityBridgeTest, HandlesCycles) {
494515
RunLoopUntilIdle();
495516

496517
EXPECT_EQ(0, semantics_manager_.DeleteCount());
497-
EXPECT_EQ(2, semantics_manager_.UpdateCount());
518+
// 1 + (2 new updates).
519+
EXPECT_EQ(3, semantics_manager_.UpdateCount());
498520
EXPECT_EQ(2, semantics_manager_.CommitCount());
499521
EXPECT_FALSE(semantics_manager_.DeleteOverflowed());
500522
EXPECT_FALSE(semantics_manager_.UpdateOverflowed());

shell/platform/fuchsia/flutter/platform_view.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,12 @@ void PlatformView::DispatchSemanticsAction(int32_t node_id,
570570
flutter::PlatformView::DispatchSemanticsAction(node_id, action, {});
571571
}
572572

573+
// |flutter::PlatformView|
574+
// |flutter_runner::AccessibilityBridge::Delegate|
575+
float PlatformView::GetViewPixelRatio() {
576+
return view_pixel_ratio_;
577+
}
578+
573579
// |flutter::PlatformView|
574580
void PlatformView::UpdateSemantics(
575581
flutter::SemanticsNodeUpdates update,

shell/platform/fuchsia/flutter/platform_view.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ class PlatformView final : public flutter::PlatformView,
7070
// |flutter_runner::AccessibilityBridge::Delegate|
7171
void DispatchSemanticsAction(int32_t node_id,
7272
flutter::SemanticsAction action) override;
73+
// |flutter_runner::AccessibilityBridge::Delegate|
74+
float GetViewPixelRatio() override;
7375

7476
// |PlatformView|
7577
flutter::PointerDataDispatcherMaker GetDispatcherMaker() override;

0 commit comments

Comments
 (0)