8317771: [macos14] Expand/collapse a JTree using keyboard freezes the application in macOS 14 Sonoma

Reviewed-by: kizune
This commit is contained in:
Artem Semenov 2024-01-17 16:44:27 +00:00
parent 4e5323538c
commit ffa33d7b80

View File

@ -36,6 +36,7 @@ import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.lang.annotation.Native;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashSet;
@ -63,6 +64,7 @@ import javax.swing.JTextArea;
import javax.swing.JList;
import javax.swing.JTree;
import javax.swing.KeyStroke;
import javax.swing.tree.TreePath;
import sun.awt.AWTAccessor;
import sun.lwawt.LWWindowPeer;
@ -757,14 +759,75 @@ class CAccessibility implements PropertyChangeListener {
return new Object[]{childrenAndRoles.get(whichChildren * 2), childrenAndRoles.get((whichChildren * 2) + 1)};
}
private static Accessible createAccessibleTreeNode(JTree t, TreePath p) {
Accessible a = null;
try {
Class<?> accessibleJTreeNodeClass = Class.forName("javax.swing.JTree$AccessibleJTree$AccessibleJTreeNode");
Constructor<?> constructor = accessibleJTreeNodeClass.getConstructor(t.getAccessibleContext().getClass(), JTree.class, TreePath.class, Accessible.class);
constructor.setAccessible(true);
a = ((Accessible) constructor.newInstance(t.getAccessibleContext(), t, p, null));
} catch (Exception e) {
e.printStackTrace();
}
return a;
}
// 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>();
Accessible at = null;
if (a instanceof CAccessible) {
at = CAccessible.getSwingAccessible(a);
} else {
at = a;
}
if (at instanceof JTree) {
JTree tree = ((JTree) at);
if (whichChildren == JAVA_AX_ALL_CHILDREN) {
int count = tree.getRowCount();
for (int i = 0; i < count; i++) {
TreePath path = tree.getPathForRow(i);
Accessible an = createAccessibleTreeNode(tree, path);
if (an != null) {
AccessibleContext ac = an.getAccessibleContext();
if (ac != null) {
allChildren.add(an);
allChildren.add(ac.getAccessibleRole());;
allChildren.add(String.valueOf((tree.isRootVisible() ? path.getPathCount() : path.getPathCount() - 1)));
}
}
}
}
if (whichChildren == JAVA_AX_SELECTED_CHILDREN) {
int count = tree.getSelectionCount();
for (int i = 0; i < count; i++) {
TreePath path = tree.getSelectionPaths()[i];
Accessible an = createAccessibleTreeNode(tree, path);
if (an != null) {
AccessibleContext ac = an.getAccessibleContext();
if (ac != null) {
allChildren.add(an);
allChildren.add(ac.getAccessibleRole());
allChildren.add(String.valueOf((tree.isRootVisible() ? path.getPathCount() : path.getPathCount() - 1)));
}
}
}
}
return allChildren.toArray();
}
ArrayList<Object> currentLevelChildren = new ArrayList<Object>();
ArrayList<Accessible> parentStack = new ArrayList<Accessible>();
parentStack.add(a);
ArrayList<Integer> indexses = new ArrayList<Integer>();