Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -43970,6 +43970,7 @@ ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/semantics/route.dart + ../../
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/semantics/scrollable.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/semantics/semantics.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/semantics/semantics_helper.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/semantics/tabs.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/semantics/tappable.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/semantics/text_field.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/lib/web_ui/lib/src/engine/services.dart + ../../../flutter/LICENSE
Expand Down Expand Up @@ -46909,6 +46910,7 @@ FILE: ../../../flutter/lib/web_ui/lib/src/engine/semantics/route.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/semantics/scrollable.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/semantics/semantics.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/semantics/semantics_helper.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/semantics/tabs.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/semantics/tappable.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/semantics/text_field.dart
FILE: ../../../flutter/lib/web_ui/lib/src/engine/services.dart
Expand Down
68 changes: 68 additions & 0 deletions lib/ui/fixtures/ui_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,74 @@ void sendSemanticsUpdate() {
_semanticsUpdate(builder.build());
}

@pragma('vm:entry-point')
void sendSemanticsUpdateWithRole() {
final SemanticsUpdateBuilder builder = SemanticsUpdateBuilder();

final Float64List transform = Float64List(16);
final Int32List childrenInTraversalOrder = Int32List(0);
final Int32List childrenInHitTestOrder = Int32List(0);
final Int32List additionalActions = Int32List(0);
transform[0] = 1;
transform[1] = 0;
transform[2] = 0;
transform[3] = 0;

transform[4] = 0;
transform[5] = 1;
transform[6] = 0;
transform[7] = 0;

transform[8] = 0;
transform[9] = 0;
transform[10] = 1;
transform[11] = 0;

transform[12] = 0;
transform[13] = 0;
transform[14] = 0;
transform[15] = 0;
builder.updateNode(
id: 0,
flags: 0,
actions: 0,
maxValueLength: 0,
currentValueLength: 0,
textSelectionBase: -1,
textSelectionExtent: -1,
platformViewId: -1,
scrollChildren: 0,
scrollIndex: 0,
scrollPosition: 0,
scrollExtentMax: 0,
scrollExtentMin: 0,
rect: Rect.fromLTRB(0, 0, 10, 10),
elevation: 0,
thickness: 0,
identifier: "identifier",
label: "label",
labelAttributes: const <StringAttribute>[],
value: "value",
valueAttributes: const <StringAttribute>[],
increasedValue: "increasedValue",
increasedValueAttributes: const <StringAttribute>[],
decreasedValue: "decreasedValue",
decreasedValueAttributes: const <StringAttribute>[],
hint: "hint",
hintAttributes: const <StringAttribute>[],
tooltip: "tooltip",
textDirection: TextDirection.ltr,
transform: transform,
childrenInTraversalOrder: childrenInTraversalOrder,
childrenInHitTestOrder: childrenInHitTestOrder,
additionalActions: additionalActions,
headingLevel: 0,
linkUrl: '',
role: SemanticsRole.tab
);
_semanticsUpdate(builder.build());
}

@pragma('vm:external-name', 'SemanticsUpdate')
external void _semanticsUpdate(SemanticsUpdate update);

Expand Down
32 changes: 30 additions & 2 deletions lib/ui/semantics.dart
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,29 @@ class SemanticsAction {
String toString() => 'SemanticsAction.$name';
}

/// An enum to describe the role for a semantics node.
///
/// The roles are translated into native accessibility roles in each platform.
enum SemanticsRole {
/// Does not represent any role.
none,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if this could use a name that describes what it does rather than what it doesn't do. Perhaps something like container? If a node doesn't have a functional/interactive role, it still pays the role to contain and position its children, if any.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find container to be a confusing name in this case. especially if it is used as an leaf node.


/// A tab button.
///
/// see also:
/// * [tabBar], which is the role for containers of tab buttons.
tab,

/// Contains tab buttons.
///
/// see also:
/// * [tab], which is the role for tab buttons.
tabBar,

/// The main display for a tab.
tabPanel,
}

/// A Boolean value that can be associated with a semantics node.
//
// When changes are made to this class, the equivalent APIs in
Expand Down Expand Up @@ -940,6 +963,7 @@ abstract class SemanticsUpdateBuilder {
required Int32List additionalActions,
int headingLevel = 0,
String linkUrl = '',
SemanticsRole role = SemanticsRole.none,
});

/// Update the custom semantics action associated with the given `id`.
Expand Down Expand Up @@ -1012,6 +1036,7 @@ base class _NativeSemanticsUpdateBuilder extends NativeFieldWrapperClass1 implem
required Int32List additionalActions,
int headingLevel = 0,
String linkUrl = '',
SemanticsRole role = SemanticsRole.none,
}) {
assert(_matrix4IsValid(transform));
assert (
Expand Down Expand Up @@ -1057,6 +1082,7 @@ base class _NativeSemanticsUpdateBuilder extends NativeFieldWrapperClass1 implem
additionalActions,
headingLevel,
linkUrl,
role.index,
);
}
@Native<
Expand Down Expand Up @@ -1099,7 +1125,8 @@ base class _NativeSemanticsUpdateBuilder extends NativeFieldWrapperClass1 implem
Handle,
Handle,
Int32,
Handle)>(symbol: 'SemanticsUpdateBuilder::updateNode')
Handle,
Int32)>(symbol: 'SemanticsUpdateBuilder::updateNode')
external void _updateNode(
int id,
int flags,
Expand Down Expand Up @@ -1138,7 +1165,8 @@ base class _NativeSemanticsUpdateBuilder extends NativeFieldWrapperClass1 implem
Int32List childrenInHitTestOrder,
Int32List additionalActions,
int headingLevel,
String linkUrl);
String linkUrl,
int role,);

@override
void updateCustomAction({required int id, String? label, String? hint, int overrideId = -1}) {
Expand Down
15 changes: 15 additions & 0 deletions lib/ui/semantics/semantics_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,19 @@ const int kHorizontalScrollSemanticsActions =
const int kScrollableSemanticsActions =
kVerticalScrollSemanticsActions | kHorizontalScrollSemanticsActions;

/// C/C++ representation of `SemanticsRole` defined in
/// `lib/ui/semantics.dart`.
///\warning This must match the `SemanticsRole` enum in
/// `lib/ui/semantics.dart`.
/// See also:
/// - file://./../../../lib/ui/semantics.dart
enum class SemanticsRole : int32_t {
kNone = 0,
kTab = 1,
kTabBar = 2,
kTabPanel = 3,
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume a C version of this change will also need to be added embedder.h?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will do that in a separate pr when i add the support to the desktop embedding. I am trying to avoid adding support for all platforms in a single pr


/// C/C++ representation of `SemanticsFlags` defined in
/// `lib/ui/semantics.dart`.
///\warning This must match the `SemanticsFlags` enum in
Expand Down Expand Up @@ -148,6 +161,8 @@ struct SemanticsNode {
int32_t headingLevel = 0;

std::string linkUrl;

SemanticsRole role;
};

// Contains semantic nodes that need to be updated.
Expand Down
4 changes: 3 additions & 1 deletion lib/ui/semantics/semantics_update_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ void SemanticsUpdateBuilder::updateNode(
const tonic::Int32List& childrenInHitTestOrder,
const tonic::Int32List& localContextActions,
int headingLevel,
std::string linkUrl) {
std::string linkUrl,
int role) {
FML_CHECK(scrollChildren == 0 ||
(scrollChildren > 0 && childrenInHitTestOrder.data()))
<< "Semantics update contained scrollChildren but did not have "
Expand Down Expand Up @@ -123,6 +124,7 @@ void SemanticsUpdateBuilder::updateNode(

node.headingLevel = headingLevel;
node.linkUrl = std::move(linkUrl);
node.role = (SemanticsRole)role;
}

void SemanticsUpdateBuilder::updateCustomAction(int id,
Expand Down
3 changes: 2 additions & 1 deletion lib/ui/semantics/semantics_update_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ class SemanticsUpdateBuilder
const tonic::Int32List& childrenInHitTestOrder,
const tonic::Int32List& customAccessibilityActions,
int headingLevel,
std::string linkUrl);
std::string linkUrl,
int role);

void updateCustomAction(int id,
std::string label,
Expand Down
43 changes: 43 additions & 0 deletions lib/ui/semantics/semantics_update_builder_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -88,5 +88,48 @@ TEST_F(SemanticsUpdateBuilderTest, CanHandleAttributedStrings) {
DestroyShell(std::move(shell), task_runners);
}

TEST_F(SemanticsUpdateBuilderTest, CanHandleSemanticsRole) {
auto message_latch = std::make_shared<fml::AutoResetWaitableEvent>();

auto nativeSemanticsUpdate = [message_latch](Dart_NativeArguments args) {
auto handle = Dart_GetNativeArgument(args, 0);
intptr_t peer = 0;
Dart_Handle result = Dart_GetNativeInstanceField(
handle, tonic::DartWrappable::kPeerIndex, &peer);
ASSERT_FALSE(Dart_IsError(result));
SemanticsUpdate* update = reinterpret_cast<SemanticsUpdate*>(peer);
SemanticsNodeUpdates nodes = update->takeNodes();
ASSERT_EQ(nodes.size(), (size_t)1);
auto node = nodes.find(0)->second;
// Should match the updateNode in ui_test.dart.
ASSERT_EQ(node.role, SemanticsRole::kTab);
message_latch->Signal();
};

Settings settings = CreateSettingsForFixture();
TaskRunners task_runners("test", // label
GetCurrentTaskRunner(), // platform
CreateNewThread(), // raster
CreateNewThread(), // ui
CreateNewThread() // io
);

AddNativeCallback("SemanticsUpdate",
CREATE_NATIVE_ENTRY(nativeSemanticsUpdate));

std::unique_ptr<Shell> shell = CreateShell(settings, task_runners);

ASSERT_TRUE(shell->IsSetup());
auto configuration = RunConfiguration::InferFromSettings(settings);
configuration.SetEntrypoint("sendSemanticsUpdateWithRole");

shell->RunEngine(std::move(configuration), [](auto result) {
ASSERT_EQ(result, Engine::RunStatus::Success);
});

message_latch->Wait();
DestroyShell(std::move(shell), task_runners);
}

} // namespace testing
} // namespace flutter
10 changes: 10 additions & 0 deletions lib/web_ui/lib/semantics.dart
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,14 @@ class SemanticsFlag {
String toString() => 'SemanticsFlag.$name';
}

// Mirrors engine/src/flutter/lib/ui/semantics.dart
enum SemanticsRole {
none,
tab,
tabBar,
tabPanel,
}

// When adding a new StringAttributeType, the classes in these file must be
// updated as well.
// * engine/src/flutter/lib/ui/semantics.dart
Expand Down Expand Up @@ -294,6 +302,7 @@ class SemanticsUpdateBuilder {
required Int32List additionalActions,
int headingLevel = 0,
String? linkUrl,
SemanticsRole role = SemanticsRole.none,
}) {
if (transform.length != 16) {
throw ArgumentError('transform argument must have 16 entries.');
Expand Down Expand Up @@ -334,6 +343,7 @@ class SemanticsUpdateBuilder {
platformViewId: platformViewId,
headingLevel: headingLevel,
linkUrl: linkUrl,
role: role,
));
}

Expand Down
1 change: 1 addition & 0 deletions lib/web_ui/lib/src/engine.dart
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ export 'engine/semantics/route.dart';
export 'engine/semantics/scrollable.dart';
export 'engine/semantics/semantics.dart';
export 'engine/semantics/semantics_helper.dart';
export 'engine/semantics/tabs.dart';
export 'engine/semantics/tappable.dart';
export 'engine/semantics/text_field.dart';
export 'engine/services/buffers.dart';
Expand Down
1 change: 1 addition & 0 deletions lib/web_ui/lib/src/engine/semantics.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@ export 'semantics/platform_view.dart';
export 'semantics/scrollable.dart';
export 'semantics/semantics.dart';
export 'semantics/semantics_helper.dart';
export 'semantics/tabs.dart';
export 'semantics/tappable.dart';
export 'semantics/text_field.dart';
Loading
Loading