Skip to content

Commit 6f3cd6b

Browse files
savoptikAnton Tarasov
authored and
Anton Tarasov
committedNov 16, 2021
8267385: Create NSAccessibilityElement implementation for JavaComponentAccessibility
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 Backport-of: 9c6457f222e702b60fef4247c3e241c669eb9491
1 parent 7758191 commit 6f3cd6b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+4776
-230
lines changed
 

‎src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java

+166-61
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,13 @@
3434
import java.awt.event.KeyEvent;
3535
import java.beans.PropertyChangeEvent;
3636
import java.beans.PropertyChangeListener;
37+
import java.lang.annotation.Native;
3738
import java.lang.reflect.InvocationTargetException;
3839
import java.util.ArrayList;
3940
import java.util.HashSet;
4041
import java.util.Set;
4142
import java.util.concurrent.Callable;
43+
import java.util.Arrays;
4244

4345
import javax.accessibility.Accessible;
4446
import javax.accessibility.AccessibleAction;
@@ -57,6 +59,8 @@
5759
import javax.swing.JLabel;
5860
import javax.swing.JMenuItem;
5961
import javax.swing.JTextArea;
62+
import javax.swing.JList;
63+
import javax.swing.JTree;
6064
import javax.swing.KeyStroke;
6165

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

118122
static <T> T invokeAndWait(final Callable<T> callable, final Component c) {
119-
if (c != null) {
120-
try {
121-
return LWCToolkit.invokeAndWait(callable, c);
122-
} catch (final Exception e) { e.printStackTrace(); }
123-
}
124-
return null;
123+
return invokeAndWait(callable, c, null);
125124
}
126125

127126
static <T> T invokeAndWait(final Callable<T> callable, final Component c, final T defValue) {
@@ -551,6 +550,10 @@ public void run() {
551550
if (pac == null) return;
552551
AccessibleSelection as = pac.getAccessibleSelection();
553552
if (as == null) return;
553+
if (parent instanceof JList) {
554+
((JList) parent).setSelectedIndex(i);
555+
return;
556+
}
554557
as.addAccessibleSelection(i);
555558
}
556559
}, c);
@@ -651,77 +654,148 @@ public boolean[] call() throws Exception {
651654

652655
// Duplicated from JavaComponentAccessibility
653656
// Note that values >=0 are indexes into the child array
654-
static final int JAVA_AX_ALL_CHILDREN = -1;
655-
static final int JAVA_AX_SELECTED_CHILDREN = -2;
656-
static final int JAVA_AX_VISIBLE_CHILDREN = -3;
657+
@Native static final int JAVA_AX_ALL_CHILDREN = -1;
658+
@Native static final int JAVA_AX_SELECTED_CHILDREN = -2;
659+
@Native static final int JAVA_AX_VISIBLE_CHILDREN = -3;
657660

658661
// Each child takes up two entries in the array: one for itself and one for its role
659662
public static Object[] getChildrenAndRoles(final Accessible a, final Component c, final int whichChildren, final boolean allowIgnored) {
660663
if (a == null) return null;
661664
return invokeAndWait(new Callable<Object[]>() {
662665
public Object[] call() throws Exception {
663-
ArrayList<Object> childrenAndRoles = new ArrayList<Object>();
664-
_addChildren(a, whichChildren, allowIgnored, childrenAndRoles);
665-
666-
/* In the case of fetching a selection, need to check to see if
667-
* the active descendant is at the beginning of the list. If it
668-
* is not it needs to be moved to the beginning of the list so
669-
* VoiceOver will annouce it correctly. The list returned
670-
* from Java is always in order from top to bottom, but when shift
671-
* selecting downward (extending the list) or multi-selecting using
672-
* the VO keys control+option+command+return the active descendant
673-
* is not at the top of the list in the shift select down case and
674-
* may not be in the multi select case.
675-
*/
676-
if (whichChildren == JAVA_AX_SELECTED_CHILDREN) {
677-
if (!childrenAndRoles.isEmpty()) {
678-
AccessibleContext activeDescendantAC =
679-
CAccessible.getActiveDescendant(a);
680-
if (activeDescendantAC != null) {
681-
String activeDescendantName =
682-
activeDescendantAC.getAccessibleName();
683-
AccessibleRole activeDescendantRole =
684-
activeDescendantAC.getAccessibleRole();
685-
// Move active descendant to front of list.
686-
// List contains pairs of each selected item's
687-
// Accessible and AccessibleRole.
688-
ArrayList<Object> newArray = new ArrayList<Object>();
689-
int count = childrenAndRoles.size();
690-
Accessible currentAccessible = null;
691-
AccessibleContext currentAC = null;
692-
String currentName = null;
693-
AccessibleRole currentRole = null;
694-
for (int i = 0; i < count; i+=2) {
695-
// Is this the active descendant?
696-
currentAccessible = (Accessible)childrenAndRoles.get(i);
697-
currentAC = currentAccessible.getAccessibleContext();
698-
currentName = currentAC.getAccessibleName();
699-
currentRole = (AccessibleRole)childrenAndRoles.get(i+1);
700-
if (currentName != null && currentName.equals(activeDescendantName) &&
701-
currentRole.equals(activeDescendantRole) ) {
702-
newArray.add(0, currentAccessible);
703-
newArray.add(1, currentRole);
704-
} else {
705-
newArray.add(currentAccessible);
706-
newArray.add(currentRole);
707-
}
708-
}
709-
childrenAndRoles = newArray;
666+
return getChildrenAndRolesImpl(a, c, whichChildren, allowIgnored);
667+
}
668+
}, c);
669+
}
670+
671+
private static Object[] getChildrenAndRolesImpl(final Accessible a, final Component c, final int whichChildren, final boolean allowIgnored) {
672+
if (a == null) return null;
673+
674+
ArrayList<Object> childrenAndRoles = new ArrayList<Object>();
675+
_addChildren(a, whichChildren, allowIgnored, childrenAndRoles);
676+
677+
/* In case of fetching a selection, we need to check if
678+
* the active descendant is at the beginning of the list, or
679+
* otherwise move it, so that VoiceOver announces it correctly.
680+
* The java list is always in order from top to bottom, but when
681+
* (1) shift-selecting downward (extending the list) or (2) multi-selecting with
682+
* the VO keys (CTRL+ALT+CMD+RETURN) the active descendant
683+
* is not at the top of the list in the 1st case and may not be in the 2nd.
684+
*/
685+
if (whichChildren == JAVA_AX_SELECTED_CHILDREN) {
686+
if (!childrenAndRoles.isEmpty()) {
687+
AccessibleContext activeDescendantAC =
688+
CAccessible.getActiveDescendant(a);
689+
if (activeDescendantAC != null) {
690+
String activeDescendantName =
691+
activeDescendantAC.getAccessibleName();
692+
AccessibleRole activeDescendantRole =
693+
activeDescendantAC.getAccessibleRole();
694+
// Move active descendant to front of list.
695+
// List contains pairs of each selected item's
696+
// Accessible and AccessibleRole.
697+
ArrayList<Object> newArray = new ArrayList<Object>();
698+
int count = childrenAndRoles.size();
699+
Accessible currentAccessible = null;
700+
AccessibleContext currentAC = null;
701+
String currentName = null;
702+
AccessibleRole currentRole = null;
703+
for (int i = 0; i < count; i += 2) {
704+
// Is this the active descendant?
705+
currentAccessible = (Accessible) childrenAndRoles.get(i);
706+
currentAC = currentAccessible.getAccessibleContext();
707+
currentName = currentAC.getAccessibleName();
708+
currentRole = (AccessibleRole) childrenAndRoles.get(i + 1);
709+
if (currentName != null && currentName.equals(activeDescendantName) &&
710+
currentRole.equals(activeDescendantRole)) {
711+
newArray.add(0, currentAccessible);
712+
newArray.add(1, currentRole);
713+
} else {
714+
newArray.add(currentAccessible);
715+
newArray.add(currentRole);
710716
}
711717
}
718+
childrenAndRoles = newArray;
712719
}
720+
}
721+
}
722+
723+
if ((whichChildren < 0) || (whichChildren * 2 >= childrenAndRoles.size())) {
724+
return childrenAndRoles.toArray();
725+
}
726+
727+
return new Object[]{childrenAndRoles.get(whichChildren * 2), childrenAndRoles.get((whichChildren * 2) + 1)};
728+
}
729+
730+
// This method is called from the native
731+
// Each child takes up three entries in the array: one for itself, one for its role, and one for the recursion level
732+
private static Object[] getChildrenAndRolesRecursive(final Accessible a, final Component c, final int whichChildren, final boolean allowIgnored, final int level) {
733+
if (a == null) return null;
734+
return invokeAndWait(new Callable<Object[]>() {
735+
public Object[] call() throws Exception {
736+
ArrayList<Object> currentLevelChildren = new ArrayList<Object>();
737+
ArrayList<Object> allChildren = new ArrayList<Object>();
738+
ArrayList<Accessible> parentStack = new ArrayList<Accessible>();
739+
parentStack.add(a);
740+
ArrayList<Integer> indexses = new ArrayList<Integer>();
741+
Integer index = 0;
742+
int currentLevel = level;
743+
while (!parentStack.isEmpty()) {
744+
Accessible p = parentStack.get(parentStack.size() - 1);
745+
746+
currentLevelChildren.addAll(Arrays.asList(getChildrenAndRolesImpl(p, c, JAVA_AX_ALL_CHILDREN, allowIgnored)));
747+
if ((currentLevelChildren.size() == 0) || (index >= currentLevelChildren.size())) {
748+
if (!parentStack.isEmpty()) parentStack.remove(parentStack.size() - 1);
749+
if (!indexses.isEmpty()) index = indexses.remove(indexses.size() - 1);
750+
currentLevel -= 1;
751+
currentLevelChildren.clear();
752+
continue;
753+
}
754+
755+
Accessible ca = null;
756+
Object obj = currentLevelChildren.get(index);
757+
if (!(obj instanceof Accessible)) {
758+
index += 2;
759+
currentLevelChildren.clear();
760+
continue;
761+
}
762+
ca = (Accessible) obj;
763+
Object role = currentLevelChildren.get(index + 1);
764+
currentLevelChildren.clear();
765+
766+
AccessibleContext cac = ca.getAccessibleContext();
767+
if (cac == null) {
768+
index += 2;
769+
continue;
770+
}
771+
772+
if ((cac.getAccessibleStateSet().contains(AccessibleState.SELECTED) && (whichChildren == JAVA_AX_SELECTED_CHILDREN)) ||
773+
(cac.getAccessibleStateSet().contains(AccessibleState.VISIBLE) && (whichChildren == JAVA_AX_VISIBLE_CHILDREN)) ||
774+
(whichChildren == JAVA_AX_ALL_CHILDREN)) {
775+
allChildren.add(ca);
776+
allChildren.add(role);
777+
allChildren.add(String.valueOf(currentLevel));
778+
}
779+
780+
index += 2;
781+
782+
if (cac.getAccessibleStateSet().contains(AccessibleState.EXPANDED)) {
783+
parentStack.add(ca);
784+
indexses.add(index);
785+
index = 0;
786+
currentLevel += 1;
787+
continue;
788+
}
713789

714-
if ((whichChildren < 0) || (whichChildren * 2 >= childrenAndRoles.size())) {
715-
return childrenAndRoles.toArray();
716790
}
717791

718-
return new Object[] { childrenAndRoles.get(whichChildren * 2), childrenAndRoles.get((whichChildren * 2) + 1) };
792+
return allChildren.toArray();
719793
}
720794
}, c);
721795
}
722796

723-
private static final int JAVA_AX_ROWS = 1;
724-
private static final int JAVA_AX_COLS = 2;
797+
@Native private static final int JAVA_AX_ROWS = 1;
798+
@Native private static final int JAVA_AX_COLS = 2;
725799

726800
public static int getTableInfo(final Accessible a, final Component c,
727801
final int info) {
@@ -740,6 +814,23 @@ public static int getTableInfo(final Accessible a, final Component c,
740814
}, c);
741815
}
742816

817+
private static int[] getTableSelectedInfo(final Accessible a, final Component c,
818+
final int info) {
819+
if (a == null) return null;
820+
return invokeAndWait(() -> {
821+
AccessibleContext ac = a.getAccessibleContext();
822+
AccessibleTable table = ac.getAccessibleTable();
823+
if (table != null) {
824+
if (info == JAVA_AX_COLS) {
825+
return table.getSelectedAccessibleColumns();
826+
} else if (info == JAVA_AX_ROWS) {
827+
return table.getSelectedAccessibleRows();
828+
}
829+
}
830+
return null;
831+
}, c);
832+
}
833+
743834
private static AccessibleRole getAccessibleRoleForLabel(JLabel l, AccessibleRole fallback) {
744835
String text = l.getText();
745836
if (text != null && text.length() > 0) {
@@ -858,4 +949,18 @@ public Long call() throws Exception {
858949
}
859950
}, (Component)ax);
860951
}
952+
953+
private static boolean isTreeRootVisible(Accessible a, Component c) {
954+
if (a == null) return false;
955+
956+
return invokeAndWait(new Callable<Boolean>() {
957+
public Boolean call() throws Exception {
958+
Accessible sa = CAccessible.getSwingAccessible(a);
959+
if (sa instanceof JTree) {
960+
return ((JTree) sa).isRootVisible();
961+
}
962+
return false;
963+
}
964+
}, c);
965+
}
861966
}

‎src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessible.java

+9-4
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,7 @@
3131

3232
import javax.accessibility.Accessible;
3333
import javax.accessibility.AccessibleContext;
34-
import javax.swing.JProgressBar;
3534
import javax.swing.JTabbedPane;
36-
import javax.swing.JSlider;
37-
import javax.swing.event.ChangeEvent;
38-
import javax.swing.event.ChangeListener;
3935

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

7977
private Accessible accessible;
8078

@@ -137,6 +135,13 @@ public void propertyChange(PropertyChangeEvent e) {
137135
if (parentAccessible != null) {
138136
parentRole = parentAccessible.getAccessibleContext().getAccessibleRole();
139137
}
138+
139+
if (newValue == AccessibleState.EXPANDED) {
140+
treeNodeExpanded(ptr);
141+
} else if (newValue == AccessibleState.COLLAPSED) {
142+
treeNodeCollapsed(ptr);
143+
}
144+
140145
// At least for now don't handle combo box menu state changes.
141146
// This may change when later fixing issues which currently
142147
// exist for combo boxes, but for now the following is only

1 commit comments

Comments
 (1)
Please sign in to comment.