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

Commit 4592116

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

6 files changed

+156
-38
lines changed

shell/platform/fuchsia/flutter/accessibility_bridge.cc

Lines changed: 60 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,61 @@ 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_location(GetNodeLocation(root_flutter_semantics_node_))
368+
.set_transform(ConvertSkiaTransformToMat4(result))
369+
.set_attributes(
370+
GetNodeAttributes(root_flutter_semantics_node_, &this_node_size))
371+
.set_states(GetNodeStates(root_flutter_semantics_node_, &this_node_size))
372+
.set_actions(
373+
GetNodeActions(root_flutter_semantics_node_, &this_node_size))
374+
.set_child_ids(child_ids);
375+
return root_fuchsia_node;
376+
}
377+
321378
void AccessibilityBridge::UpdateScreenRects() {
322379
std::unordered_set<int32_t> visited_nodes;
323380
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+
// Get 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: 24 additions & 5 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+
// 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[1], 1.f);
288+
}
289+
272290
TEST_F(AccessibilityBridgeTest, PopulatesHiddenState) {
273291
flutter::SemanticsNode node0;
274292
node0.id = 0;
@@ -399,9 +417,10 @@ TEST_F(AccessibilityBridgeTest, TruncatesLargeValue) {
399417
RunLoopUntilIdle();
400418

401419
EXPECT_EQ(0, semantics_manager_.DeleteCount());
402-
EXPECT_EQ(1, semantics_manager_.UpdateCount());
420+
EXPECT_EQ(2, semantics_manager_.UpdateCount());
403421
EXPECT_EQ(1, semantics_manager_.CommitCount());
404-
EXPECT_EQ(3U, semantics_manager_.LastUpdatedNodes().size());
422+
// Root node is in the first update.
423+
EXPECT_EQ(2U, semantics_manager_.LastUpdatedNodes().size());
405424
auto trimmed_node =
406425
std::find_if(semantics_manager_.LastUpdatedNodes().begin(),
407426
semantics_manager_.LastUpdatedNodes().end(),

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;

shell/platform/fuchsia/flutter/platform_view_unittest.cc

Lines changed: 55 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ class PlatformViewTests : public testing::Test {
4242
FML_DISALLOW_COPY_AND_ASSIGN(PlatformViewTests);
4343
};
4444

45+
// class FuchsiaPlatformViewDelegate final : public
46+
// flutter_runner::PlatformView::Delegate {
47+
// float GetViewPixelRatio() {
48+
// return 1.f;
49+
// }
50+
// };
51+
4552
class MockExternalViewEmbedder : public flutter::ExternalViewEmbedder {
4653
public:
4754
MockExternalViewEmbedder() = default;
@@ -153,12 +160,13 @@ TEST_F(PlatformViewTests, ChangesAccessibilitySettings) {
153160

154161
EXPECT_FALSE(delegate.SemanticsEnabled());
155162
EXPECT_EQ(delegate.SemanticsFeatures(), 0);
156-
163+
// FuchsiaPlatformViewDelegate fuchsia_delegate;
157164
auto platform_view = flutter_runner::PlatformView(
158-
delegate, // delegate
159-
"test_platform_view", // label
160-
std::move(view_ref), // view_ref
161-
std::move(task_runners), // task_runners
165+
delegate, // delegate
166+
"test_platform_view", // label
167+
std::move(view_ref), // view_ref
168+
std::move(task_runners), // task_runners
169+
// fuchsia_delegate, // FuchsiaExternalViewEmbedder
162170
services_provider.service_directory(), // runner_services
163171
nullptr, // parent_environment_service_provider_handle
164172
nullptr, // session_listener_request
@@ -210,11 +218,14 @@ TEST_F(PlatformViewTests, EnableWireframeTest) {
210218
wireframe_enabled = should_enable;
211219
};
212220

221+
// FuchsiaPlatformViewDelegate fuchsia_delegate;
213222
auto platform_view = flutter_runner::PlatformView(
214-
delegate, // delegate
215-
"test_platform_view", // label
216-
std::move(view_ref), // view_refs
217-
std::move(task_runners), // task_runners
223+
delegate, // delegate
224+
"test_platform_view", // label
225+
std::move(view_ref), // view_refs
226+
std::move(task_runners), // task_runners
227+
// fuchsia_delegate, //
228+
// FuchsiaExternalViewEmbedder
218229
services_provider.service_directory(), // runner_services
219230
nullptr, // parent_environment_service_provider_handle
220231
nullptr, // session_listener_request
@@ -277,11 +288,14 @@ TEST_F(PlatformViewTests, CreateViewTest) {
277288
int64_t view_id, bool hit_testable,
278289
bool focusable) { create_view_called = true; };
279290

291+
// FuchsiaPlatformViewDelegate fuchsia_delegate;
280292
auto platform_view = flutter_runner::PlatformView(
281-
delegate, // delegate
282-
"test_platform_view", // label
283-
std::move(view_ref), // view_refs
284-
std::move(task_runners), // task_runners
293+
delegate, // delegate
294+
"test_platform_view", // label
295+
std::move(view_ref), // view_refs
296+
std::move(task_runners), // task_runners
297+
// fuchsia_delegate, //
298+
// FuchsiaExternalViewEmbedder
285299
services_provider.service_directory(), // runner_services
286300
nullptr, // parent_environment_service_provider_handle
287301
nullptr, // session_listener_request
@@ -346,11 +360,14 @@ TEST_F(PlatformViewTests, UpdateViewTest) {
346360
int64_t view_id, bool hit_testable,
347361
bool focusable) { update_view_called = true; };
348362

363+
// FuchsiaPlatformViewDelegate fuchsia_delegate;
349364
auto platform_view = flutter_runner::PlatformView(
350-
delegate, // delegate
351-
"test_platform_view", // label
352-
std::move(view_ref), // view_refs
353-
std::move(task_runners), // task_runners
365+
delegate, // delegate
366+
"test_platform_view", // label
367+
std::move(view_ref), // view_refs
368+
std::move(task_runners), // task_runners
369+
// fuchsia_delegate, //
370+
// FuchsiaExternalViewEmbedder
354371
services_provider.service_directory(), // runner_services
355372
nullptr, // parent_environment_service_provider_handle
356373
nullptr, // session_listener_request
@@ -415,11 +432,14 @@ TEST_F(PlatformViewTests, DestroyViewTest) {
415432
destroy_view_called = true;
416433
};
417434

435+
// FuchsiaPlatformViewDelegate fuchsia_delegate;
418436
auto platform_view = flutter_runner::PlatformView(
419-
delegate, // delegate
420-
"test_platform_view", // label
421-
std::move(view_ref), // view_refs
422-
std::move(task_runners), // task_runners
437+
delegate, // delegate
438+
"test_platform_view", // label
439+
std::move(view_ref), // view_refs
440+
std::move(task_runners), // task_runners
441+
// fuchsia_delegate, //
442+
// FuchsiaExternalViewEmbedder
423443
services_provider.service_directory(), // runner_services
424444
nullptr, // parent_environment_service_provider_handle
425445
nullptr, // session_listener_request
@@ -478,11 +498,14 @@ TEST_F(PlatformViewTests, RequestFocusTest) {
478498
fidl::BindingSet<fuchsia::ui::views::Focuser> focuser_bindings;
479499
auto focuser_handle = focuser_bindings.AddBinding(&mock_focuser);
480500

501+
// FuchsiaPlatformViewDelegate fuchsia_delegate;
481502
auto platform_view = flutter_runner::PlatformView(
482-
delegate, // delegate
483-
"test_platform_view", // label
484-
std::move(view_ref), // view_refs
485-
std::move(task_runners), // task_runners
503+
delegate, // delegate
504+
"test_platform_view", // label
505+
std::move(view_ref), // view_refs
506+
std::move(task_runners), // task_runners
507+
// fuchsia_delegate, //
508+
// FuchsiaExternalViewEmbedder
486509
services_provider.service_directory(), // runner_services
487510
nullptr, // parent_environment_service_provider_handle
488511
nullptr, // session_listener_request
@@ -553,11 +576,14 @@ TEST_F(PlatformViewTests, CreateSurfaceTest) {
553576
"PlatformViewTest", &view_embedder, gr_context.get());
554577
};
555578

579+
// FuchsiaPlatformViewDelegate fuchsia_delegate;
556580
auto platform_view = flutter_runner::PlatformView(
557-
delegate, // delegate
558-
"test_platform_view", // label
559-
std::move(view_ref), // view_refs
560-
std::move(task_runners), // task_runners
581+
delegate, // delegate
582+
"test_platform_view", // label
583+
std::move(view_ref), // view_refs
584+
std::move(task_runners), // task_runners
585+
// fuchsia_delegate, //
586+
// FuchsiaExternalViewEmbedder
561587
services_provider.service_directory(), // runner_services
562588
nullptr, // parent_environment_service_provider_handle
563589
nullptr, // session_listener_request

0 commit comments

Comments
 (0)