Skip to content

Commit

Permalink
8317771: [macos14] Expand/collapse a JTree using keyboard freezes the…
Browse files Browse the repository at this point in the history
… application in macOS 14 Sonoma

Reviewed-by: kizune
  • Loading branch information
savoptik committed Jan 17, 2024
1 parent 4e53235 commit ffa33d7
Showing 1 changed file with 64 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
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;
Expand Down Expand Up @@ -63,6 +64,7 @@
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;
Expand Down Expand Up @@ -757,14 +759,75 @@ private static Object[] getChildrenAndRolesImpl(Accessible a, Component c, int w
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>();
Expand Down

0 comments on commit ffa33d7

Please sign in to comment.