@@ -11,6 +11,7 @@ import org.jetbrains.skiko.MainUIDispatcher
1111import org.jetbrains.skiko.OS
1212import org.jetbrains.skiko.hostOs
1313import org.jetbrains.skiko.initializeCAccessible
14+ import androidx.compose.ui.scene.skia.SkiaLayerComponent
1415
1516/* *
1617 * A helper class for requesting accessibility focus on a given accessible.
@@ -29,6 +30,8 @@ internal class AccessibleFocusHelper(
2930
3031 @OptIn(DelicateCoroutinesApi ::class )
3132 fun requestFocusOnAccessible (accessible : Accessible ? ) {
33+ initializeAccessible(accessible)
34+
3235 focusedAccessible = accessible
3336
3437 when (hostOs) {
@@ -83,29 +86,22 @@ internal class AccessibleFocusHelper(
8386}
8487
8588/* *
86- * This method should be called on custom [Accessible] creation (or its context if context is
87- * created lazily).
88- *
89- * JDK's accessibility support (at least for macOS) builds mapping AccessibleContext -> Accessible.
90- * Some [Accessible]s are built only when focus is settled and
91- * since we have a hack [AccessibleFocusHelper.requestFocusOnAccessible], wrong mapping
92- * can be built (ComponentAccessibleContext -> SkiaLayer instead of
93- * ComponentAccessibleContext -> ComponentAccessible).
89+ * [sun.lwawt.macosx.CAccessible.getCAccessible] builds a mapping of [AccessibleContext] to
90+ * [sun.lwawt.macosx.CAccessible] instances (which wrap the corresponding [Accessible]).
91+ * If it is called with the Skia layer content [Accessible] (=[SkiaLayerComponent.contentRoot])
92+ * while the [AccessibleFocusHelper] hack is active ([AccessibleFocusHelper.focusedAccessible] is
93+ * not `null`), it builds an incorrect mapping, associating the focused [AccessibleContext] with
94+ * [SkiaLayerComponent.contentRoot].
9495 *
95- * This method forces JDK's accessibility support to cache mapping
96- * ComponentAccessibleContext -> ComponentAccessible, if it is called on
97- * ComponentAccessibleContext creation .
96+ * To work around this problem, [initializeAccessible] explicitly calls
97+ * [sun.lwawt.macosx.CAccessible.getCAccessible] on the focused [Accessible], forcing the correct
98+ * association to be made. Future calls then just retrieve the already stored value .
9899 *
99- * Related to the [issue](https://youtrack.jetbrains.com/issue/COMPOSE-176).
100+ * See also [Error when following the instructions of
101+ * VoiceOver](https://youtrack.jetbrains.com/issue/CMP-176).
100102 */
101- internal fun initializeAccessible (accessible : Accessible ) {
102- when (hostOs) {
103- OS .MacOS -> {
104- initializeCAccessible(accessible)
105- }
106-
107- else -> {
108- // TODO: do we need something for Windows?
109- }
103+ private fun initializeAccessible (accessible : Accessible ? ) {
104+ if ((accessible != null ) && (hostOs == OS .MacOS )) {
105+ initializeCAccessible(accessible)
110106 }
111107}
0 commit comments