Skip to content

Commit b652766

Browse files
igordmnmazunin-v-jb
authored andcommitted
Desktop. Don't use AccessibleRole.PANEL for root/unknown nodes (fixes issues on Windows) (#885)
This fixes issues on Windows: 1. Windows pronounced "Panel unavailable" at start 2. When we focus on Switch or Box(Modifier.clickable), there was "Panel0" pronounced. Now it says nothing. 3. After merging #881, we refocus the main component. This leads to pronouncing the window title, now it says nothing, as the accessible root node is unknown on macOs it changes one thing: 1. When we focus on Switch or Box(Modifier.clickable), now it prounonces that we in scroll area (if we in scroll area). It also pronounces it for other compnents like Button/Text ## Testing Manually with accessibility enabled in run1 (Windows, macOs)
1 parent 65fd240 commit b652766

File tree

3 files changed

+55
-3
lines changed

3 files changed

+55
-3
lines changed

compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/ComposeAccessible.kt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,13 @@ internal class ComposeAccessible(
171171
val progressBarRangeInfo
172172
get() = semanticsNode.config.getOrNull(SemanticsProperties.ProgressBarRangeInfo)
173173

174+
val isContainer
175+
@Suppress("DEPRECATION")
176+
get() = semanticsNode.config.getOrNull(SemanticsProperties.IsContainer)
177+
178+
val isTraversalGroup
179+
get() = semanticsNode.config.getOrNull(SemanticsProperties.IsTraversalGroup)
180+
174181
private fun makeScrollbarChild(
175182
vertical: Boolean
176183
): Accessible {
@@ -402,7 +409,9 @@ internal class ComposeAccessible(
402409
setText != null -> AccessibleRole.TEXT
403410
text != null -> AccessibleRole.LABEL
404411
progressBarRangeInfo != null -> AccessibleRole.PROGRESS_BAR
405-
else -> AccessibleRole.PANEL
412+
isContainer != null -> AccessibleRole.GROUP_BOX
413+
isTraversalGroup != null -> AccessibleRole.GROUP_BOX
414+
else -> AccessibleRole.UNKNOWN
406415
}
407416
}
408417

compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/ComposeSceneAccessible.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ internal class ComposeSceneAccessible(
153153
}
154154

155155
override fun getAccessibleRole(): AccessibleRole {
156-
return AccessibleRole.PANEL
156+
return AccessibleRole.UNKNOWN
157157
}
158158

159159
override fun getAccessibleStateSet(): AccessibleStateSet {

compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/platform/AccessibilityTest.kt

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package androidx.compose.ui.platform
1818

19+
import androidx.compose.foundation.layout.Box
1920
import androidx.compose.material.Button
2021
import androidx.compose.material.LinearProgressIndicator
2122
import androidx.compose.material.Tab
@@ -25,6 +26,8 @@ import androidx.compose.ui.Modifier
2526
import androidx.compose.ui.assertThat
2627
import androidx.compose.ui.isEqualTo
2728
import androidx.compose.ui.semantics.Role
29+
import androidx.compose.ui.semantics.isContainer
30+
import androidx.compose.ui.semantics.isTraversalGroup
2831
import androidx.compose.ui.semantics.role
2932
import androidx.compose.ui.semantics.semantics
3033
import androidx.compose.ui.test.SemanticsNodeInteraction
@@ -126,9 +129,49 @@ class AccessibilityTest {
126129
}
127130
}
128131

132+
@Test
133+
fun boxHasUnknownRole() {
134+
rule.setContent {
135+
Box(Modifier.testTag("box"))
136+
}
137+
138+
rule.onNodeWithTag("box").apply {
139+
val context = ComposeAccessible(fetchSemanticsNode()).accessibleContext!!
140+
assertThat(context.accessibleRole).isEqualTo(AccessibleRole.UNKNOWN)
141+
}
142+
}
143+
144+
@Suppress("DEPRECATION")
145+
@Test
146+
fun containerHasGroupRole() {
147+
rule.setContent {
148+
Box(Modifier.testTag("box").semantics {
149+
isContainer = true
150+
})
151+
}
152+
153+
rule.onNodeWithTag("box").apply {
154+
val context = ComposeAccessible(fetchSemanticsNode()).accessibleContext!!
155+
assertThat(context.accessibleRole).isEqualTo(AccessibleRole.GROUP_BOX)
156+
}
157+
}
158+
159+
@Test
160+
fun traversalGroupHasGroupRole() {
161+
rule.setContent {
162+
Box(Modifier.testTag("box").semantics {
163+
isTraversalGroup = true
164+
})
165+
}
166+
167+
rule.onNodeWithTag("box").apply {
168+
val context = ComposeAccessible(fetchSemanticsNode()).accessibleContext!!
169+
assertThat(context.accessibleRole).isEqualTo(AccessibleRole.GROUP_BOX)
170+
}
171+
}
172+
129173
private fun SemanticsNodeInteraction.assertHasAccessibleRole(role: AccessibleRole) {
130174
val accessibleContext = ComposeAccessible(fetchSemanticsNode()).accessibleContext!!
131175
assertThat(accessibleContext.accessibleRole).isEqualTo(role)
132176
}
133-
134177
}

0 commit comments

Comments
 (0)