Skip to content

Commit

Permalink
Add a new property shouldCenterActivationPoint to NIViewAccessibili…
Browse files Browse the repository at this point in the history
…tyElement.

This property ensures multiline NIViewAccessibilityElements have unique touch points when merging multiline links into a single NIViewAccessibilityElement. When the first link contains either the first or the last word in the sentence and the second link spills between more than one line, the NIViewAccessibilityElement frames have the same top left point, which is used as the touch point. This causes an issue where NIAttributedLabel can't determine which accessibilityElement a touchPoint originated from, meaning that one of the  two links can't register events. We solve this by using the center point of the frame, which is ensured to be unique (only for links in the same text) as multiline element frames would have unique y-coordinates.

PiperOrigin-RevId: 544181302
  • Loading branch information
Nobody authored and material-automation committed Jun 28, 2023
1 parent 390b1ce commit 1e03c49
Showing 1 changed file with 20 additions and 0 deletions.
20 changes: 20 additions & 0 deletions src/attributedlabel/src/NIAttributedLabel.m
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,17 @@ @interface NIViewAccessibilityElement ()
// performed.
@property (nonatomic) BOOL isContainerDataValid;

// This property ensures multiline NIViewAccessibilityElements have unique
// touch points when merging multiline links into a single NIViewAccessibilityElement.
// When the first link contains either the first or the last word in the sentence and the second
// link spills between more than one line, the NIViewAccessibilityElement
// frames have the same top left point, which is used as the touch point. This causes an
// issue where NIAttributedLabel can't determine which accessibilityElement a touchPoint
// originated from, meaning that one of the two links can't register events.
// We solve this by using the center point of the frame, which is ensured to be unique
// (only for links in the same text) as multiline element frames would have unique y-coordinates.
@property (nonatomic) BOOL shouldCenterActivationPoint;

@end

@implementation NIViewAccessibilityElement
Expand Down Expand Up @@ -204,6 +215,7 @@ - (instancetype)initWithAccessibilityContainer:(id)container {
frameInContainer:CGRectZero
pointsInContainer:nil]) {
self.isContainerDataValid = NO;
self.shouldCenterActivationPoint = NO;
}
return self;
}
Expand Down Expand Up @@ -273,6 +285,13 @@ - (CGPoint)accessibilityActivationPoint {
point = [accessibilityContainerView.window convertPoint:point toWindow:nil];
return point;
}
if (_shouldCenterActivationPoint) {
// Since links cannot overlap, using the center of the start and end points
// of the explicit link location ensures unique touch points from events.
CGPoint startPoint = [[_pointsInContainer firstObject] CGPointValue];
CGPoint endPoint = [[_pointsInContainer lastObject] CGPointValue];
return CGPointMake((startPoint.x+endPoint.x)/2.0, (startPoint.y+endPoint.y)/2.0);
}
return super.accessibilityActivationPoint;
}

Expand Down Expand Up @@ -1911,6 +1930,7 @@ - (NSArray *)accessibleElements {
NIViewAccessibilityElement *element = [[NIViewAccessibilityElement alloc]
initWithAccessibilityContainer:self
frameInContainer:rectValue.CGRectValue];
element.shouldCenterActivationPoint = _shouldMergeMultilineLinks;
[self updateAccessibilityLabelOnElement:element withAccessibilityLabel:label];

// Set the frame to fallback on if |element|'s accessibility container is changed
Expand Down

0 comments on commit 1e03c49

Please sign in to comment.