未验证 提交 96f5f5b9 编写于 作者: J Jonah Williams 提交者: GitHub

Semantics framework updates (#5601)

上级 4c9f40a3
......@@ -27,6 +27,7 @@ class SemanticsAction {
static const int _kDidGainAccessibilityFocusIndex = 1 << 15;
static const int _kDidLoseAccessibilityFocusIndex = 1 << 16;
static const int _kCustomAction = 1 << 17;
static const int _kDismissIndex = 1 << 18;
/// The numerical value for this action.
///
......@@ -148,11 +149,20 @@ class SemanticsAction {
static const SemanticsAction didLoseAccessibilityFocus = const SemanticsAction._(_kDidLoseAccessibilityFocusIndex);
/// Indicates that the user has invoked a custom accessibility action.
///
///
/// This handler is added automatically whenever a custom accessibility
/// action is added to a semantics node.
static const SemanticsAction customAction = const SemanticsAction._(_kCustomAction);
/// A request that the node should be dismissed.
///
/// A [Snackbar], for example, may have a dismiss action to indicate to the
/// user that it can be removed after it is no longer relevant. On Android,
/// (with TalkBack) special hint text is spoken when focusing the node and
/// a custom action is availible in the local context menu. On iOS,
/// (with VoiceOver) users can perform a standard gesture to dismiss it.
static const SemanticsAction dismiss = const SemanticsAction._(_kDismissIndex);
/// The possible semantics actions.
///
/// The map's key is the [index] of the action and the value is the action
......@@ -176,6 +186,7 @@ class SemanticsAction {
_kDidGainAccessibilityFocusIndex: didGainAccessibilityFocus,
_kDidLoseAccessibilityFocusIndex: didLoseAccessibilityFocus,
_kCustomAction: customAction,
_kDismissIndex: dismiss,
};
@override
......@@ -217,6 +228,8 @@ class SemanticsAction {
return 'SemanticsAction.didLoseAccessibilityFocus';
case _kCustomAction:
return 'SemanticsAction.customAction';
case _kDismissIndex:
return 'SemanticsAction.dismiss';
}
return null;
}
......@@ -238,6 +251,10 @@ class SemanticsFlag {
static const int _kScopesRouteIndex= 1 << 11;
static const int _kNamesRouteIndex = 1 << 12;
static const int _kIsHiddenIndex = 1 << 13;
static const int _kIsImageIndex = 1 << 14;
static const int _kIsLiveRegionIndex = 1 << 15;
static const int _kHasToggledStateIndex = 1 << 16;
static const int _kIsToggledIndex = 1 << 17;
const SemanticsFlag._(this.index);
......@@ -248,7 +265,13 @@ class SemanticsFlag {
/// The semantics node has the quality of either being "checked" or "unchecked".
///
/// This flag is mutually exclusive with [hasToggledState].
///
/// For example, a checkbox or a radio button widget has checked state.
///
/// See also:
///
/// * [SemanticsFlag.isChecked], which controls whether the node is "checked" or "unchecked".
static const SemanticsFlag hasCheckedState = const SemanticsFlag._(_kHasCheckedStateIndex);
/// Whether a semantics node that [hasCheckedState] is checked.
......@@ -257,6 +280,10 @@ class SemanticsFlag {
/// "unchecked".
///
/// For example, if a checkbox has a visible checkmark, [isChecked] is true.
///
/// See also:
///
/// * [SemanticsFlag.hasCheckedState], which enables a checked state.
static const SemanticsFlag isChecked = const SemanticsFlag._(_kIsCheckedIndex);
......@@ -376,6 +403,44 @@ class SemanticsFlag {
/// used to implement accessibility scrolling on iOS.
static const SemanticsFlag isHidden = const SemanticsFlag._(_kIsHiddenIndex);
/// Whether the semantics node represents an image.
///
/// Both TalkBack and VoiceOver will inform the user the the semantics node
/// represents an image.
static const SemanticsFlag isImage = const SemanticsFlag._(_kIsImageIndex);
/// Whether the semantics node is a live region.
///
/// A live region indicates that updates to semantics node are important.
/// Platforms may use this information to make polite announcements to the
/// user to inform them of updates to this node.
///
/// An example of a live region is a [SnackBar] widget. On Android, A live
/// region causes a polite announcement to be generated automatically, even
/// if the user does not have focus of the widget.
static const SemanticsFlag isLiveRegion = const SemanticsFlag._(_kIsLiveRegionIndex);
/// The semantics node has the quality of either being "on" or "off".
///
/// This flag is mutually exclusive with [hasCheckedState].
///
/// For example, a switch has toggled state.
///
/// See also:
///
/// * [SemanticsFlag.isToggled], which controls whether the node is "on" or "off".
static const SemanticsFlag hasToggledState = const SemanticsFlag._(_kHasToggledStateIndex);
/// If true, the semantics node is "on". If false, the semantics node is
/// "off".
///
/// For example, if a switch is in the on position, [isToggled] is true.
///
/// See also:
///
/// * [SemanticsFlag.hasToggledState], which enables a toggled state.
static const SemanticsFlag isToggled = const SemanticsFlag._(_kIsToggledIndex);
/// The possible semantics flags.
///
/// The map's key is the [index] of the flag and the value is the flag itself.
......@@ -394,6 +459,10 @@ class SemanticsFlag {
_kScopesRouteIndex: scopesRoute,
_kNamesRouteIndex: namesRoute,
_kIsHiddenIndex: isHidden,
_kIsImageIndex: isImage,
_kIsLiveRegionIndex: isLiveRegion,
_kHasToggledStateIndex: hasToggledState,
_kIsToggledIndex: isToggled,
};
@override
......@@ -427,6 +496,14 @@ class SemanticsFlag {
return 'SemanticsFlag.namesRoute';
case _kIsHiddenIndex:
return 'SemanticsFlag.isHidden';
case _kIsImageIndex:
return 'SemanticsFlag.isImage';
case _kIsLiveRegionIndex:
return 'SemanticsFlag.isLiveRegion';
case _kHasToggledStateIndex:
return 'SemanticsFlag.hasToggledState';
case _kIsToggledIndex:
return 'SemanticsFlag.isToggled';
}
return null;
}
......@@ -563,8 +640,8 @@ class SemanticsUpdateBuilder extends NativeFieldWrapperClass2 {
) native 'SemanticsUpdateBuilder_updateNode';
/// Update the custom accessibility action associated with the given `id`.
///
/// The name of the action exposed to the user is the `label`. The text
///
/// The name of the action exposed to the user is the `label`. The text
/// direction of this label is the same as the global window.
void updateCustomAction({int id, String label}) {
assert(id != null);
......
......@@ -36,6 +36,7 @@ enum class SemanticsAction : int32_t {
kDidGainAccessibilityFocus = 1 << 15,
kDidLoseAccessibilityFocus = 1 << 16,
kCustomAction = 1 << 17,
kDismiss = 1 << 18,
};
const int kScrollableSemanticsActions =
......@@ -60,6 +61,10 @@ enum class SemanticsFlags : int32_t {
kScopesRoute = 1 << 11,
kNamesRoute = 1 << 12,
kIsHidden = 1 << 13,
kIsImage = 1 << 14,
kIsLiveRegion = 1 << 15,
kHasToggledState = 1 << 16,
kIsToggled = 1 << 17,
};
struct SemanticsNode {
......
......@@ -42,8 +42,7 @@ blink::SemanticsAction GetSemanticsActionForScrollDirection(
} // namespace
@implementation FlutterCustomAccessibilityAction
{
@implementation FlutterCustomAccessibilityAction {
}
@end
......@@ -185,12 +184,12 @@ blink::SemanticsAction GetSemanticsActionForScrollDirection(
return NO;
int32_t action_id = action.uid;
std::vector<uint8_t> args;
args.push_back(3); // type=int32.
args.push_back(3); // type=int32.
args.push_back(action_id);
args.push_back(action_id >> 8);
args.push_back(action_id >> 16);
args.push_back(action_id >> 24);
[self bridge] ->DispatchSemanticsAction([self uid], blink::SemanticsAction::kCustomAction, args);
[self bridge] -> DispatchSemanticsAction([self uid], blink::SemanticsAction::kCustomAction, args);
return YES;
}
......@@ -313,6 +312,13 @@ blink::SemanticsAction GetSemanticsActionForScrollDirection(
return YES;
}
- (BOOL)accessibilityPerformEscape {
if (![self node].HasAction(blink::SemanticsAction::kDismiss))
return NO;
[self bridge] -> DispatchSemanticsAction([self uid], blink::SemanticsAction::kDismiss);
return YES;
}
#pragma mark UIAccessibilityFocus overrides
- (void)accessibilityElementDidBecomeFocused {
......@@ -361,7 +367,9 @@ blink::SemanticsAction GetSemanticsActionForScrollDirection(
[self node].HasAction(blink::SemanticsAction::kDecrease)) {
traits |= UIAccessibilityTraitAdjustable;
}
// TODO(jonahwilliams): switches should have a value of "on" or "off"
if ([self node].HasFlag(blink::SemanticsFlags::kIsSelected) ||
[self node].HasFlag(blink::SemanticsFlags::kIsToggled) ||
[self node].HasFlag(blink::SemanticsFlags::kIsChecked)) {
traits |= UIAccessibilityTraitSelected;
}
......@@ -375,6 +383,12 @@ blink::SemanticsAction GetSemanticsActionForScrollDirection(
if ([self node].HasFlag(blink::SemanticsFlags::kIsHeader)) {
traits |= UIAccessibilityTraitHeader;
}
if ([self node].HasFlag(blink::SemanticsFlags::kIsImage)) {
traits |= UIAccessibilityTraitImage;
}
if ([self node].HasFlag(blink::SemanticsFlags::kIsLiveRegion)) {
traits |= UIAccessibilityTraitUpdatesFrequently;
}
return traits;
}
......@@ -504,7 +518,7 @@ void AccessibilityBridge::UpdateSemantics(blink::SemanticsNodeUpdates nodes,
blink::CustomAccessibilityActionUpdates actions) {
BOOL layoutChanged = NO;
BOOL scrollOccured = NO;
for (const auto& entry: actions) {
for (const auto& entry : actions) {
const blink::CustomAccessibilityAction& action = entry.second;
actions_[action.id] = action;
}
......@@ -524,14 +538,16 @@ void AccessibilityBridge::UpdateSemantics(blink::SemanticsNodeUpdates nodes,
}
object.children = newChildren;
if (node.customAccessibilityActions.size() > 0) {
NSMutableArray<FlutterCustomAccessibilityAction*>* accessibilityCustomActions =
NSMutableArray<FlutterCustomAccessibilityAction*>* accessibilityCustomActions =
[[[NSMutableArray alloc] init] autorelease];
for (int32_t action_id : node.customAccessibilityActions) {
blink::CustomAccessibilityAction& action = actions_[action_id];
NSString* label = @(action.label.data());
SEL selector = @selector(onCustomAccessibilityAction:);
FlutterCustomAccessibilityAction* customAction =
[[FlutterCustomAccessibilityAction alloc] initWithName:label target:object selector:selector];
FlutterCustomAccessibilityAction* customAction =
[[FlutterCustomAccessibilityAction alloc] initWithName:label
target:object
selector:selector];
customAction.uid = action_id;
[accessibilityCustomActions addObject:customAction];
}
......@@ -597,10 +613,10 @@ void AccessibilityBridge::DispatchSemanticsAction(int32_t uid, blink::SemanticsA
platform_view_->DispatchSemanticsAction(uid, action, args);
}
void AccessibilityBridge::DispatchSemanticsAction(int32_t uid,
blink::SemanticsAction action,
void AccessibilityBridge::DispatchSemanticsAction(int32_t uid,
blink::SemanticsAction action,
std::vector<uint8_t> args) {
platform_view_->DispatchSemanticsAction(uid, action, args);
platform_view_->DispatchSemanticsAction(uid, action, args);
}
SemanticsObject* AccessibilityBridge::GetOrCreateObject(int32_t uid,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册