IDEA-320485 Accessibility: Fix announcing notification at the start of the IDE

The problem is in the caller: we find a label, give it to the native, but native doesn't have a native accessible context yet, because the initialization is lazy and VoiceOver hasn't been requested it.
Now we take IdeRootPane as a caller.

GitOrigin-RevId: de04373d3098fa434efbc4bab746eb8b878f861c
This commit is contained in:
Aydar Mukhametzyanov
2023-05-19 13:26:00 +02:00
committed by intellij-monorepo-bot
parent 276a423660
commit ae0413924c
3 changed files with 28 additions and 2 deletions

View File

@@ -319,4 +319,5 @@ stripe.right.accessible.group.name=Right Stripe
toolbar.group.default.accessible.group.name=Toolbar
toolbar.group.right.accessible.group.name=Right Toolbar
toolbar.group.left.accessible.group.name=Left Toolbar
root.pane.accessible.group.name=Root Pane
light.bulb.panel.accessible.name=Light Bulb

View File

@@ -10,6 +10,7 @@ import com.intellij.openapi.project.Project
import com.intellij.openapi.util.registry.Registry
import com.intellij.openapi.util.text.StringUtil
import com.intellij.openapi.wm.WindowManager
import com.intellij.openapi.wm.impl.IdeRootPane
import com.intellij.util.ui.EDT
import com.intellij.util.ui.UIUtil
import com.intellij.util.ui.accessibility.AccessibleAnnouncerUtil
@@ -59,6 +60,8 @@ object NotificationsAnnouncer {
}
private fun findCaller(frame: JFrame): Accessible? {
(frame.rootPane as? IdeRootPane)?.let { return it }
var caller = callersCache.firstOrNull { it.isValid && it.frame === frame }?.accessible
if (caller == null){
callersCache.removeAll { !it.isValid }
@@ -76,7 +79,8 @@ object NotificationsAnnouncer {
private fun announceComponents(components: List<String>, caller: Accessible, mode: Int) {
val text = StringUtil.join(components, ". ")
if (LOG.isDebugEnabled) LOG.debug("Notification will be announced with mode=$mode, from caller=$caller, text=$text")
if (LOG.isDebugEnabled)
LOG.info("Notification will be announced with mode=$mode, from caller=$caller, text=$text")
AccessibleAnnouncerUtil.announce(caller, text, mode != 1)
}
@@ -119,6 +123,6 @@ object NotificationsAnnouncer {
val frame: JFrame? get() = frameWeak.get()
val accessible: Accessible? get() = accessibleWeak.get()
val isValid: Boolean get() = frame != null &&
accessible?.let { it is JComponent && it.isVisible } == true
accessible?.let { it is JComponent && it.isVisible && it.isValid } == true
}
}

View File

@@ -53,6 +53,8 @@ import com.jetbrains.JBR
import org.jetbrains.annotations.ApiStatus
import java.awt.*
import java.awt.event.MouseMotionAdapter
import javax.accessibility.AccessibleContext
import javax.accessibility.AccessibleRole
import javax.swing.*
private const val EXTENSION_KEY = "extensionKey"
@@ -260,6 +262,25 @@ open class IdeRootPane internal constructor(frame: JFrame,
return toolWindowPane!!
}
override fun getAccessibleContext(): AccessibleContext {
return if (SystemInfo.isMac) {
if (accessibleContext == null) {
// We need to turn IdeRootPane into an accessible group in order to make notifications announcing working
accessibleContext = object : AccessibleJRootPane() {
override fun getAccessibleRole(): AccessibleRole {
return AccessibleRole.GROUP_BOX
}
override fun getAccessibleName(): String {
return UIBundle.message("root.pane.accessible.group.name")
}
}
}
accessibleContext
}
else super.getAccessibleContext()
}
open fun getToolWindowPane(): ToolWindowPane = toolWindowPane!!
private fun updateScreenState(isInFullScreen: () -> Boolean) {