Skip to content
Permalink
Browse files
8267385: Create NSAccessibilityElement implementation for JavaCompone…
…ntAccessibility

8262031: Create implementation for NSAccessibilityNavigableStaticText protocol
8264287: Create implementation for NSAccessibilityComboBox protocol peer
8264303: Create implementation for NSAccessibilityTabGroup protocol peer
8264292: Create implementation for NSAccessibilityList protocol peer
8267387: Create implementation for NSAccessibilityOutline protocol
8267388: Create implementation for NSAccessibilityTable protocol
8264286: Create implementation for NSAccessibilityColumn protocol peer
8264298: Create implementation for NSAccessibilityRow protocol peer
8264291: Create implementation for NSAccessibilityCell protocol peer

Reviewed-by: kizune, pbansal, serb
  • Loading branch information
savoptik authored and Anton Tarasov committed Aug 9, 2021
1 parent 0ac2be9 commit 9c6457f222e702b60fef4247c3e241c669eb9491
Showing with 4,776 additions and 230 deletions.
  1. +166 −61 src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java
  2. +9 −4 src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessible.java
  3. +27 −34 src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m
  4. +4 −0 src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityAction.h
  5. +32 −0 src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityAction.m
  6. +4 −0 src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityUtilities.h
  7. +86 −2 src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityUtilities.m
  8. +22 −76 src/java.desktop/macosx/native/libawt_lwawt/awt/JavaComponentAccessibility.m
  9. +0 −17 src/java.desktop/macosx/native/libawt_lwawt/awt/JavaTextAccessibility.m
  10. +11 −1 src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ButtonAccessibility.m
  11. +28 −0 src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CellAccessibility.h
  12. +86 −0 src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CellAccessibility.m
  13. +1 −1 src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CheckboxAccessibility.m
  14. +31 −0 src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ColumnAccessibility.h
  15. +112 −0 src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ColumnAccessibility.m
  16. +28 −0 src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComboBoxAccessibility.h
  17. +68 −0 src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ComboBoxAccessibility.m
  18. +69 −9 src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonComponentAccessibility.h
  19. +1,046 −8 src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonComponentAccessibility.m
  20. +1 −1 src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonTextAccessibility.m
  21. +13 −2 src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/GroupAccessibility.m
  22. +11 −1 src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ImageAccessibility.m
  23. +28 −0 src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListAccessibility.h
  24. +63 −0 src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListAccessibility.m
  25. +28 −0 src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListRowAccessibility.h
  26. +75 −0 src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ListRowAccessibility.m
  27. +31 −0 src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/NavigableTextAccessibility.h
  28. +316 −0 src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/NavigableTextAccessibility.m
  29. +33 −0 src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineAccessibility.h
  30. +56 −0 src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineAccessibility.m
  31. +33 −0 src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineRowAccessibility.h
  32. +111 −0 src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineRowAccessibility.m
  33. +1 −1 src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/RadiobuttonAccessibility.m
  34. +9 −8 src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/ScrollAreaAccessibility.m
  35. +12 −2 src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/SliderAccessibility.m
  36. +12 −2 src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/SpinboxAccessibility.m
  37. +10 −0 src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/StaticTextAccessibility.m
  38. +37 −0 src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabButtonAccessibility.h
  39. +107 −0 src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabButtonAccessibility.m
  40. +37 −0 src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabGroupAccessibility.h
  41. +204 −0 src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TabGroupAccessibility.m
  42. +33 −0 src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableAccessibility.h
  43. +241 −0 src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableAccessibility.m
  44. +31 −0 src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableRowAccessibility.h
  45. +145 −0 src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/TableRowAccessibility.m
  46. +119 −0 test/jdk/java/awt/a11y/AccessibleComponentTest.java
  47. +80 −0 test/jdk/java/awt/a11y/AccessibleJComboboxTest.java
  48. +330 −0 test/jdk/java/awt/a11y/AccessibleJListTest.java
  49. +93 −0 test/jdk/java/awt/a11y/AccessibleJTabbedPaneTest.java
  50. +114 −0 test/jdk/java/awt/a11y/AccessibleJTableTest.java
  51. +239 −0 test/jdk/java/awt/a11y/AccessibleJTreeTest.java
  52. +293 −0 test/jdk/java/awt/a11y/AccessibleTextTest.java
@@ -34,11 +34,13 @@
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.lang.annotation.Native;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.Arrays;

import javax.accessibility.Accessible;
import javax.accessibility.AccessibleAction;
@@ -57,6 +59,8 @@
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JTextArea;
import javax.swing.JList;
import javax.swing.JTree;
import javax.swing.KeyStroke;

import sun.awt.AWTAccessor;
@@ -120,12 +124,7 @@ public void propertyChange(final PropertyChangeEvent evt) {
private native void focusChanged();

static <T> T invokeAndWait(final Callable<T> callable, final Component c) {
if (c != null) {
try {
return LWCToolkit.invokeAndWait(callable, c);
} catch (final Exception e) { e.printStackTrace(); }
}
return null;
return invokeAndWait(callable, c, null);
}

static <T> T invokeAndWait(final Callable<T> callable, final Component c, final T defValue) {
@@ -555,6 +554,10 @@ public void run() {
if (pac == null) return;
AccessibleSelection as = pac.getAccessibleSelection();
if (as == null) return;
if (parent instanceof JList) {
((JList) parent).setSelectedIndex(i);
return;
}
as.addAccessibleSelection(i);
}
}, c);
@@ -655,77 +658,148 @@ public Accessible call() throws Exception {

// Duplicated from JavaComponentAccessibility
// Note that values >=0 are indexes into the child array
static final int JAVA_AX_ALL_CHILDREN = -1;
static final int JAVA_AX_SELECTED_CHILDREN = -2;
static final int JAVA_AX_VISIBLE_CHILDREN = -3;
@Native static final int JAVA_AX_ALL_CHILDREN = -1;
@Native static final int JAVA_AX_SELECTED_CHILDREN = -2;
@Native static final int JAVA_AX_VISIBLE_CHILDREN = -3;

// Each child takes up two entries in the array: one for itself and one for its role
public static Object[] getChildrenAndRoles(final Accessible a, final Component c, final int whichChildren, final boolean allowIgnored) {
if (a == null) return null;
return invokeAndWait(new Callable<Object[]>() {
public Object[] call() throws Exception {
ArrayList<Object> childrenAndRoles = new ArrayList<Object>();
_addChildren(a, whichChildren, allowIgnored, childrenAndRoles);

/* In the case of fetching a selection, need to check to see if
* the active descendant is at the beginning of the list. If it
* is not it needs to be moved to the beginning of the list so
* VoiceOver will annouce it correctly. The list returned
* from Java is always in order from top to bottom, but when shift
* selecting downward (extending the list) or multi-selecting using
* the VO keys control+option+command+return the active descendant
* is not at the top of the list in the shift select down case and
* may not be in the multi select case.
*/
if (whichChildren == JAVA_AX_SELECTED_CHILDREN) {
if (!childrenAndRoles.isEmpty()) {
AccessibleContext activeDescendantAC =
CAccessible.getActiveDescendant(a);
if (activeDescendantAC != null) {
String activeDescendantName =
activeDescendantAC.getAccessibleName();
AccessibleRole activeDescendantRole =
activeDescendantAC.getAccessibleRole();
// Move active descendant to front of list.
// List contains pairs of each selected item's
// Accessible and AccessibleRole.
ArrayList<Object> newArray = new ArrayList<Object>();
int count = childrenAndRoles.size();
Accessible currentAccessible = null;
AccessibleContext currentAC = null;
String currentName = null;
AccessibleRole currentRole = null;
for (int i = 0; i < count; i+=2) {
// Is this the active descendant?
currentAccessible = (Accessible)childrenAndRoles.get(i);
currentAC = currentAccessible.getAccessibleContext();
currentName = currentAC.getAccessibleName();
currentRole = (AccessibleRole)childrenAndRoles.get(i+1);
if (currentName != null && currentName.equals(activeDescendantName) &&
currentRole.equals(activeDescendantRole) ) {
newArray.add(0, currentAccessible);
newArray.add(1, currentRole);
} else {
newArray.add(currentAccessible);
newArray.add(currentRole);
}
}
childrenAndRoles = newArray;
return getChildrenAndRolesImpl(a, c, whichChildren, allowIgnored);
}
}, c);
}

private static Object[] getChildrenAndRolesImpl(final Accessible a, final Component c, final int whichChildren, final boolean allowIgnored) {
if (a == null) return null;

ArrayList<Object> childrenAndRoles = new ArrayList<Object>();
_addChildren(a, whichChildren, allowIgnored, childrenAndRoles);

/* In case of fetching a selection, we need to check if
* the active descendant is at the beginning of the list, or
* otherwise move it, so that VoiceOver announces it correctly.
* The java list is always in order from top to bottom, but when
* (1) shift-selecting downward (extending the list) or (2) multi-selecting with
* the VO keys (CTRL+ALT+CMD+RETURN) the active descendant
* is not at the top of the list in the 1st case and may not be in the 2nd.
*/
if (whichChildren == JAVA_AX_SELECTED_CHILDREN) {
if (!childrenAndRoles.isEmpty()) {
AccessibleContext activeDescendantAC =
CAccessible.getActiveDescendant(a);
if (activeDescendantAC != null) {
String activeDescendantName =
activeDescendantAC.getAccessibleName();
AccessibleRole activeDescendantRole =
activeDescendantAC.getAccessibleRole();
// Move active descendant to front of list.
// List contains pairs of each selected item's
// Accessible and AccessibleRole.
ArrayList<Object> newArray = new ArrayList<Object>();
int count = childrenAndRoles.size();
Accessible currentAccessible = null;
AccessibleContext currentAC = null;
String currentName = null;
AccessibleRole currentRole = null;
for (int i = 0; i < count; i += 2) {
// Is this the active descendant?
currentAccessible = (Accessible) childrenAndRoles.get(i);
currentAC = currentAccessible.getAccessibleContext();
currentName = currentAC.getAccessibleName();
currentRole = (AccessibleRole) childrenAndRoles.get(i + 1);
if (currentName != null && currentName.equals(activeDescendantName) &&
currentRole.equals(activeDescendantRole)) {
newArray.add(0, currentAccessible);
newArray.add(1, currentRole);
} else {
newArray.add(currentAccessible);
newArray.add(currentRole);
}
}
childrenAndRoles = newArray;
}
}
}

if ((whichChildren < 0) || (whichChildren * 2 >= childrenAndRoles.size())) {
return childrenAndRoles.toArray();
}

return new Object[]{childrenAndRoles.get(whichChildren * 2), childrenAndRoles.get((whichChildren * 2) + 1)};
}

// This method is called from the native
// Each child takes up three entries in the array: one for itself, one for its role, and one for the recursion level
private static Object[] getChildrenAndRolesRecursive(final Accessible a, final Component c, final int whichChildren, final boolean allowIgnored, final int level) {
if (a == null) return null;
return invokeAndWait(new Callable<Object[]>() {
public Object[] call() throws Exception {
ArrayList<Object> currentLevelChildren = new ArrayList<Object>();
ArrayList<Object> allChildren = new ArrayList<Object>();
ArrayList<Accessible> parentStack = new ArrayList<Accessible>();
parentStack.add(a);
ArrayList<Integer> indexses = new ArrayList<Integer>();
Integer index = 0;
int currentLevel = level;
while (!parentStack.isEmpty()) {
Accessible p = parentStack.get(parentStack.size() - 1);

currentLevelChildren.addAll(Arrays.asList(getChildrenAndRolesImpl(p, c, JAVA_AX_ALL_CHILDREN, allowIgnored)));
if ((currentLevelChildren.size() == 0) || (index >= currentLevelChildren.size())) {
if (!parentStack.isEmpty()) parentStack.remove(parentStack.size() - 1);
if (!indexses.isEmpty()) index = indexses.remove(indexses.size() - 1);
currentLevel -= 1;
currentLevelChildren.clear();
continue;
}

Accessible ca = null;
Object obj = currentLevelChildren.get(index);
if (!(obj instanceof Accessible)) {
index += 2;
currentLevelChildren.clear();
continue;
}
ca = (Accessible) obj;
Object role = currentLevelChildren.get(index + 1);
currentLevelChildren.clear();

AccessibleContext cac = ca.getAccessibleContext();
if (cac == null) {
index += 2;
continue;
}

if ((cac.getAccessibleStateSet().contains(AccessibleState.SELECTED) && (whichChildren == JAVA_AX_SELECTED_CHILDREN)) ||
(cac.getAccessibleStateSet().contains(AccessibleState.VISIBLE) && (whichChildren == JAVA_AX_VISIBLE_CHILDREN)) ||
(whichChildren == JAVA_AX_ALL_CHILDREN)) {
allChildren.add(ca);
allChildren.add(role);
allChildren.add(String.valueOf(currentLevel));
}

index += 2;

if (cac.getAccessibleStateSet().contains(AccessibleState.EXPANDED)) {
parentStack.add(ca);
indexses.add(index);
index = 0;
currentLevel += 1;
continue;
}

if ((whichChildren < 0) || (whichChildren * 2 >= childrenAndRoles.size())) {
return childrenAndRoles.toArray();
}

return new Object[] { childrenAndRoles.get(whichChildren * 2), childrenAndRoles.get((whichChildren * 2) + 1) };
return allChildren.toArray();
}
}, c);
}

private static final int JAVA_AX_ROWS = 1;
private static final int JAVA_AX_COLS = 2;
@Native private static final int JAVA_AX_ROWS = 1;
@Native private static final int JAVA_AX_COLS = 2;

public static int getTableInfo(final Accessible a, final Component c,
final int info) {
@@ -744,6 +818,23 @@ public static int getTableInfo(final Accessible a, final Component c,
}, c);
}

private static int[] getTableSelectedInfo(final Accessible a, final Component c,
final int info) {
if (a == null) return null;
return invokeAndWait(() -> {
AccessibleContext ac = a.getAccessibleContext();
AccessibleTable table = ac.getAccessibleTable();
if (table != null) {
if (info == JAVA_AX_COLS) {
return table.getSelectedAccessibleColumns();
} else if (info == JAVA_AX_ROWS) {
return table.getSelectedAccessibleRows();
}
}
return null;
}, c);
}

private static AccessibleRole getAccessibleRoleForLabel(JLabel l, AccessibleRole fallback) {
String text = l.getText();
if (text != null && text.length() > 0) {
@@ -862,4 +953,18 @@ public Long call() throws Exception {
}
}, (Component)ax);
}

private static boolean isTreeRootVisible(Accessible a, Component c) {
if (a == null) return false;

return invokeAndWait(new Callable<Boolean>() {
public Boolean call() throws Exception {
Accessible sa = CAccessible.getSwingAccessible(a);
if (sa instanceof JTree) {
return ((JTree) sa).isRootVisible();
}
return false;
}
}, c);
}
}
@@ -31,11 +31,7 @@

import javax.accessibility.Accessible;
import javax.accessibility.AccessibleContext;
import javax.swing.JProgressBar;
import javax.swing.JTabbedPane;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import static javax.accessibility.AccessibleContext.ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY;
import static javax.accessibility.AccessibleContext.ACCESSIBLE_CARET_PROPERTY;
@@ -75,6 +71,8 @@ public static CAccessible getCAccessible(final Accessible a) {
private static native void menuOpened(long ptr);
private static native void menuClosed(long ptr);
private static native void menuItemSelected(long ptr);
private static native void treeNodeExpanded(long ptr);
private static native void treeNodeCollapsed(long ptr);

private Accessible accessible;

@@ -137,6 +135,13 @@ public void propertyChange(PropertyChangeEvent e) {
if (parentAccessible != null) {
parentRole = parentAccessible.getAccessibleContext().getAccessibleRole();
}

if (newValue == AccessibleState.EXPANDED) {
treeNodeExpanded(ptr);
} else if (newValue == AccessibleState.COLLAPSED) {
treeNodeCollapsed(ptr);
}

// At least for now don't handle combo box menu state changes.
// This may change when later fixing issues which currently
// exist for combo boxes, but for now the following is only

3 comments on commit 9c6457f

@savoptik

This comment has been minimized.

Copy link
Contributor Author

@savoptik savoptik replied Nov 11, 2021

/backport jdk17u

@openjdk

This comment has been minimized.

Copy link

@openjdk openjdk bot replied Nov 11, 2021

@savoptik @savoptik the backport was successfully created on the branch savoptik-backport-9c6457f2 in my personal fork of openjdk/jdk17u. To create a pull request with this backport targeting openjdk/jdk17u:master, just click the following link:

➡️ Create pull request

The title of the pull request is automatically filled in correctly and below you find a suggestion for the pull request body:

Hi all,

this pull request contains a backport of commit 9c6457f2 from the openjdk/jdk repository.

The commit being backported was authored by Artem Semenov on 9 Aug 2021 and was reviewed by Alexander Zuev, Pankaj Bansal and Sergey Bylokhov.

Thanks!

If you need to update the source branch of the pull then run the following commands in a local clone of your personal fork of openjdk/jdk17u:

$ git fetch https://github.com/openjdk-bots/jdk17u savoptik-backport-9c6457f2:savoptik-backport-9c6457f2
$ git checkout savoptik-backport-9c6457f2
# make changes
$ git add paths/to/changed/files
$ git commit --message 'Describe additional changes made'
$ git push https://github.com/openjdk-bots/jdk17u savoptik-backport-9c6457f2
Please sign in to comment.