Unverified Commit ed8ee560 authored by Aleksandr Veselov's avatar Aleksandr Veselov Committed by GitHub

Support focus management for accessibility (#501)

Required by androidx#200
parent e6c1570a
...@@ -4,12 +4,12 @@ import kotlinx.coroutines.CoroutineScope ...@@ -4,12 +4,12 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.awt.Canvas import java.awt.*
import java.awt.Component
import java.awt.Graphics
import java.awt.event.InputMethodEvent import java.awt.event.InputMethodEvent
import java.beans.PropertyChangeEvent
import javax.accessibility.Accessible import javax.accessibility.Accessible
import javax.accessibility.AccessibleContext import javax.accessibility.AccessibleContext
import javax.swing.Timer
import kotlin.time.ExperimentalTime import kotlin.time.ExperimentalTime
internal open class HardwareLayer( internal open class HardwareLayer(
...@@ -82,10 +82,27 @@ internal open class HardwareLayer( ...@@ -82,10 +82,27 @@ internal open class HardwareLayer(
private external fun getWindowHandle(platformInfo: Long): Long private external fun getWindowHandle(platformInfo: Long): Long
private val _externalAccessible = externalAccessibleFactory?.invoke(this) private val _externalAccessible = externalAccessibleFactory?.invoke(this)
private var _focusedAccessible: Accessible? = null
override fun getAccessibleContext(): AccessibleContext { override fun getAccessibleContext(): AccessibleContext {
val res = _externalAccessible?.accessibleContext val res = (_focusedAccessible ?: _externalAccessible)?.accessibleContext
return res ?: super.getAccessibleContext() return res ?: super.getAccessibleContext()
} }
val resetFocusAccessibleTimer: Timer = Timer(100) { _focusedAccessible = null }
fun requestNativeFocusOnAccessible(accessible: Accessible?) {
_focusedAccessible = accessible
val focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager()
val listeners = focusManager.getPropertyChangeListeners("focusOwner")
val event = PropertyChangeEvent(focusManager, "focusOwner", null, accessible)
listeners.forEach { it.propertyChange(event) }
// Listener spawns asynchronous notification post procedure, reading current focus owner
// and its accessibility context. This timer is used to deal with concurrency
// TODO Find more reliable procedure
resetFocusAccessibleTimer.restart()
}
} }
/** /**
......
...@@ -528,6 +528,10 @@ actual open class SkiaLayer internal constructor( ...@@ -528,6 +528,10 @@ actual open class SkiaLayer internal constructor(
} }
return rounded.toInt() return rounded.toInt()
} }
fun requestNativeFocusOnAccessible(accessible: Accessible?) {
backedLayer.requestNativeFocusOnAccessible(accessible)
}
} }
/** /**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment