Skip to content

Commit

Permalink
addressing comments
Browse files Browse the repository at this point in the history
  • Loading branch information
chunhtai committed May 3, 2021
1 parent 929a166 commit ca9f26e
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 35 deletions.
13 changes: 6 additions & 7 deletions shell/platform/darwin/ios/framework/Source/SemanticsObject.mm
Original file line number Diff line number Diff line change
Expand Up @@ -274,17 +274,16 @@ - (BOOL)isAccessibilityElement {
if ([self node].HasFlag(flutter::SemanticsFlags::kScopesRoute))
return false;

// If the only flag(s) set are scrolling related AND
// The only flags set are not kIsHidden OR
// The node doesn't have a label, value, or hint OR
// The only actions set are scrolling related actions.
// If the node is scrollable AND hidden OR
// The node has a label, value, or hint OR
// The node has non-scrolling related actions.
//
// The kIsHidden flag set with any other flag just means this node is now
// The kIsHidden flag set with the scrollable flag means this node is now
// hidden but still is a valid target for a11y focus in the tree, e.g. a list
// item that is currently off screen but the a11y navigation needs to know
// about.
return (([self node].flags & ~flutter::kScrollableSemanticsFlags) != 0 &&
([self node].flags & ~static_cast<int32_t>(flutter::SemanticsFlags::kIsHidden)) != 1) ||
return (([self node].flags & flutter::kScrollableSemanticsFlags) != 0 &&
([self node].flags & static_cast<int32_t>(flutter::SemanticsFlags::kIsHidden)) != 0) ||
![self node].label.empty() || ![self node].value.empty() || ![self node].hint.empty() ||
([self node].actions & ~flutter::kScrollableSemanticsActions) != 0;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,12 @@ class AccessibilityBridge final : public AccessibilityBridgeIos {

private:
SemanticsObject* GetOrCreateObject(int32_t id, flutter::SemanticsNodeUpdates& updates);
SemanticsObject* FindFirstFocusable(SemanticsObject* object);
SemanticsObject* FindNextFocusableIfNecessary();
// Finds the first focusable SemanticsObject rooted at the parent. This includes the parent itself
// if it is a focusable SemanticsObject.
//
// If the parent is nil, this function use the root SemanticsObject as the parent.
SemanticsObject* FindFirstFocusable(SemanticsObject* parent);
void VisitObjectsRecursivelyAndRemove(SemanticsObject* object,
NSMutableArray<NSNumber*>* doomed_uids);
void HandleEvent(NSDictionary<NSString*, id>* annotatedEvent);
Expand Down
49 changes: 22 additions & 27 deletions shell/platform/darwin/ios/framework/Source/accessibility_bridge.mm
Original file line number Diff line number Diff line change
Expand Up @@ -216,35 +216,14 @@ void PostAccessibilityNotification(UIAccessibilityNotifications notification,
}

if (layoutChanged) {
SemanticsObject* nextToFocus = nil;
// This property will be -1 if the focus is outside of the flutter
// application. In this case, we should not refocus anything.
if (last_focused_semantics_object_id_ != kSemanticObjectIdInvalid) {
// Tries to refocus the previous focused semantics object to avoid random jumps.
nextToFocus = [objects_.get() objectForKey:@(last_focused_semantics_object_id_)];
if (nextToFocus) {
nextToFocus = FindFirstFocusable(nextToFocus);
} else if (root) {
nextToFocus = FindFirstFocusable(root);
}
}
ios_delegate_->PostAccessibilityNotification(UIAccessibilityLayoutChangedNotification,
nextToFocus);
FindNextFocusableIfNecessary());
} else if (scrollOccured) {
// TODO(chunhtai): figure out what string to use for notification. At this
// point, it is guarantee the previous focused object is still in the tree
// so that we don't need to worry about focus lost. (e.g. "Screen 0 of 3")
SemanticsObject* nextToFocus = nil;
if (last_focused_semantics_object_id_ != kSemanticObjectIdInvalid) {
nextToFocus = [objects_.get() objectForKey:@(last_focused_semantics_object_id_)];
if (nextToFocus) {
nextToFocus = FindFirstFocusable(nextToFocus);
} else if (root) {
nextToFocus = FindFirstFocusable(root);
}
}
ios_delegate_->PostAccessibilityNotification(UIAccessibilityPageScrolledNotification,
nextToFocus);
FindNextFocusableIfNecessary());
}
}

Expand Down Expand Up @@ -328,12 +307,28 @@ static bool DidFlagChange(const flutter::SemanticsNode& oldNode,
VisitObjectsRecursivelyAndRemove(child, doomed_uids);
}

SemanticsObject* AccessibilityBridge::FindFirstFocusable(SemanticsObject* object) {
if (object.isAccessibilityElement) {
return object;
SemanticsObject* AccessibilityBridge::FindNextFocusableIfNecessary() {
// This property will be -1 if the focus is outside of the flutter
// application. In this case, we should not refocus anything.
if (last_focused_semantics_object_id_ == kSemanticObjectIdInvalid) {
return nil;
}

// Tries to refocus the previous focused semantics object to avoid random jumps.
return FindFirstFocusable([objects_.get() objectForKey:@(last_focused_semantics_object_id_)]);
}

SemanticsObject* AccessibilityBridge::FindFirstFocusable(SemanticsObject* parent) {
SemanticsObject* currentObject = parent ?: objects_.get()[@(kRootNodeId)];
;
if (!currentObject)
return nil;

if (currentObject.isAccessibilityElement) {
return currentObject;
}

for (SemanticsObject* child in [object children]) {
for (SemanticsObject* child in [currentObject children]) {
SemanticsObject* candidate = FindFirstFocusable(child);
if (candidate) {
return candidate;
Expand Down

0 comments on commit ca9f26e

Please sign in to comment.