-
Notifications
You must be signed in to change notification settings - Fork 6k
Handle a11y focus event on Ios and android #41777
Changes from all commits
4858609
45b8b13
7860617
7d44ee2
ec80ed3
72803e1
7218a2f
fbde877
6d2eb06
b7628cb
804ee5b
1e45108
052e7fa
b9456ca
9da2c8c
82cf3e2
f3a3b27
958c1af
6a12f87
a9167ba
e0ab00a
156ebca
7f829e8
f18b6e1
423d556
dd5191e
3a8bb9e
242aeba
73fb81a
751180d
bf97dba
78a0708
8e85983
2e06b28
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -44,12 +44,16 @@ | |
| import android.view.accessibility.AccessibilityNodeInfo; | ||
| import androidx.test.core.app.ApplicationProvider; | ||
| import androidx.test.ext.junit.runners.AndroidJUnit4; | ||
| import io.flutter.embedding.engine.FlutterJNI; | ||
| import io.flutter.embedding.engine.dart.DartExecutor; | ||
| import io.flutter.embedding.engine.systemchannels.AccessibilityChannel; | ||
| import io.flutter.plugin.common.BasicMessageChannel; | ||
| import io.flutter.plugin.platform.PlatformViewsAccessibilityDelegate; | ||
| import io.flutter.view.AccessibilityBridge.Flag; | ||
| import java.nio.ByteBuffer; | ||
| import java.nio.charset.Charset; | ||
| import java.util.ArrayList; | ||
| import java.util.HashMap; | ||
| import java.util.List; | ||
| import org.junit.Test; | ||
| import org.junit.runner.RunWith; | ||
|
|
@@ -1827,6 +1831,66 @@ public void releaseDropsChannelMessageHandler() { | |
| verify(mockChannel, never()).setAccessibilityFeatures(anyInt()); | ||
| } | ||
|
|
||
| @Test | ||
| public void sendFocusAccessibilityEvent() { | ||
| AccessibilityManager mockManager = mock(AccessibilityManager.class); | ||
| AccessibilityChannel accessibilityChannel = | ||
| new AccessibilityChannel(mock(DartExecutor.class), mock(FlutterJNI.class)); | ||
|
|
||
| ContentResolver mockContentResolver = mock(ContentResolver.class); | ||
| View mockRootView = mock(View.class); | ||
| Context context = mock(Context.class); | ||
| when(mockRootView.getContext()).thenReturn(context); | ||
| when(context.getPackageName()).thenReturn("test"); | ||
| ViewParent mockParent = mock(ViewParent.class); | ||
| when(mockRootView.getParent()).thenReturn(mockParent); | ||
| when(mockManager.isEnabled()).thenReturn(true); | ||
|
|
||
| AccessibilityBridge accessibilityBridge = | ||
| setUpBridge(mockRootView, accessibilityChannel, mockManager, null, null, null); | ||
|
|
||
| HashMap<String, Object> arguments = new HashMap<>(); | ||
| arguments.put("type", "focus"); | ||
| arguments.put("nodeId", 123); | ||
| BasicMessageChannel.Reply reply = mock(BasicMessageChannel.Reply.class); | ||
| accessibilityChannel.parsingMessageHandler.onMessage(arguments, reply); | ||
|
|
||
| // Check that focus event was sent. | ||
| ArgumentCaptor<AccessibilityEvent> eventCaptor = | ||
| ArgumentCaptor.forClass(AccessibilityEvent.class); | ||
| verify(mockParent).requestSendAccessibilityEvent(eq(mockRootView), eventCaptor.capture()); | ||
| AccessibilityEvent event = eventCaptor.getAllValues().get(0); | ||
| assertEquals(event.getEventType(), AccessibilityEvent.TYPE_VIEW_FOCUSED); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. also check for id?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree with this!
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I tested nodeId in AccessibilityChannelTest.java
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems to not be addressed yet per our offline discussion we talked previously, we can create a mocked event spy on the setSource |
||
| assertEquals(event.getSource(), null); | ||
| } | ||
|
|
||
| @Test | ||
| public void SetSourceAndPackageNameForAccessibilityEvent() { | ||
| AccessibilityManager mockManager = mock(AccessibilityManager.class); | ||
| ContentResolver mockContentResolver = mock(ContentResolver.class); | ||
| View mockRootView = mock(View.class); | ||
| Context context = mock(Context.class); | ||
| when(mockRootView.getContext()).thenReturn(context); | ||
| when(context.getPackageName()).thenReturn("test"); | ||
| when(mockManager.isEnabled()).thenReturn(true); | ||
| ViewParent mockParent = mock(ViewParent.class); | ||
| when(mockRootView.getParent()).thenReturn(mockParent); | ||
| AccessibilityEvent mockEvent = mock(AccessibilityEvent.class); | ||
|
|
||
| AccessibilityBridge accessibilityBridge = | ||
| setUpBridge(mockRootView, null, mockManager, null, null, null); | ||
|
|
||
| AccessibilityBridge spyAccessibilityBridge = spy(accessibilityBridge); | ||
|
|
||
| when(spyAccessibilityBridge.obtainAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED)) | ||
| .thenReturn(mockEvent); | ||
|
|
||
| spyAccessibilityBridge.sendAccessibilityEvent(123, AccessibilityEvent.TYPE_VIEW_FOCUSED); | ||
|
|
||
| verify(mockEvent).setPackageName("test"); | ||
| verify(mockEvent).setSource(eq(mockRootView), eq(123)); | ||
| } | ||
|
|
||
| AccessibilityBridge setUpBridge() { | ||
| return setUpBridge(null, null, null, null, null, null); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -362,6 +362,10 @@ static bool DidFlagChange(const flutter::SemanticsNode& oldNode, | |
| NSString* message = annotatedEvent[@"data"][@"message"]; | ||
| ios_delegate_->PostAccessibilityNotification(UIAccessibilityAnnouncementNotification, message); | ||
| } | ||
| if ([type isEqualToString:@"focus"]) { | ||
| SemanticsObject* node = objects_.get()[annotatedEvent[@"nodeId"]]; | ||
| ios_delegate_->PostAccessibilityNotification(UIAccessibilityLayoutChangedNotification, node); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What happens if
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Tested in my device, if node is nil, nothing will happen, the focus will not be changed |
||
| } | ||
| } | ||
|
|
||
| fml::WeakPtr<AccessibilityBridge> AccessibilityBridge::GetWeakPtr() { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.