Skip to content

Commit 35d9f97

Browse files
committed
8329667: [macos] Issue with JTree related fix for JDK-8317771
Backport-of: 05f13e7
1 parent 9eab2ce commit 35d9f97

File tree

3 files changed

+104
-72
lines changed

3 files changed

+104
-72
lines changed

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

Lines changed: 10 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -35,10 +35,11 @@
3535
import java.beans.PropertyChangeEvent;
3636
import java.beans.PropertyChangeListener;
3737
import java.lang.annotation.Native;
38-
import java.lang.reflect.Constructor;
3938
import java.lang.reflect.InvocationTargetException;
4039
import java.util.ArrayList;
40+
import java.util.HashMap;
4141
import java.util.HashSet;
42+
import java.util.List;
4243
import java.util.Set;
4344
import java.util.concurrent.Callable;
4445
import java.util.Arrays;
@@ -64,7 +65,6 @@
6465
import javax.swing.JList;
6566
import javax.swing.JTree;
6667
import javax.swing.KeyStroke;
67-
import javax.swing.tree.TreePath;
6868

6969
import sun.awt.AWTAccessor;
7070
import sun.lwawt.LWWindowPeer;
@@ -742,84 +742,28 @@ private static Object[] getChildrenAndRolesImpl(Accessible a, Component c, int w
742742
return new Object[]{childrenAndRoles.get(whichChildren * 2), childrenAndRoles.get((whichChildren * 2) + 1)};
743743
}
744744

745-
private static Accessible createAccessibleTreeNode(JTree t, TreePath p) {
746-
Accessible a = null;
747-
748-
try {
749-
Class<?> accessibleJTreeNodeClass = Class.forName("javax.swing.JTree$AccessibleJTree$AccessibleJTreeNode");
750-
Constructor<?> constructor = accessibleJTreeNodeClass.getConstructor(t.getAccessibleContext().getClass(), JTree.class, TreePath.class, Accessible.class);
751-
constructor.setAccessible(true);
752-
a = ((Accessible) constructor.newInstance(t.getAccessibleContext(), t, p, null));
753-
} catch (Exception e) {
754-
e.printStackTrace();
755-
}
756-
757-
return a;
758-
}
759-
760745
// This method is called from the native
761746
// Each child takes up three entries in the array: one for itself, one for its role, and one for the recursion level
762747
private static Object[] getChildrenAndRolesRecursive(final Accessible a, final Component c, final int whichChildren, final boolean allowIgnored, final int level) {
763748
if (a == null) return null;
764749
return invokeAndWait(new Callable<Object[]>() {
765750
public Object[] call() throws Exception {
766751
ArrayList<Object> allChildren = new ArrayList<Object>();
767-
768-
Accessible at = null;
769-
if (a instanceof CAccessible) {
770-
at = CAccessible.getSwingAccessible(a);
771-
} else {
772-
at = a;
773-
}
774-
775-
if (at instanceof JTree) {
776-
JTree tree = ((JTree) at);
777-
778-
if (whichChildren == JAVA_AX_ALL_CHILDREN) {
779-
int count = tree.getRowCount();
780-
for (int i = 0; i < count; i++) {
781-
TreePath path = tree.getPathForRow(i);
782-
Accessible an = createAccessibleTreeNode(tree, path);
783-
if (an != null) {
784-
AccessibleContext ac = an.getAccessibleContext();
785-
if (ac != null) {
786-
allChildren.add(an);
787-
allChildren.add(ac.getAccessibleRole());;
788-
allChildren.add(String.valueOf((tree.isRootVisible() ? path.getPathCount() : path.getPathCount() - 1)));
789-
}
790-
}
791-
}
792-
}
793-
794-
if (whichChildren == JAVA_AX_SELECTED_CHILDREN) {
795-
int count = tree.getSelectionCount();
796-
for (int i = 0; i < count; i++) {
797-
TreePath path = tree.getSelectionPaths()[i];
798-
Accessible an = createAccessibleTreeNode(tree, path);
799-
if (an != null) {
800-
AccessibleContext ac = an.getAccessibleContext();
801-
if (ac != null) {
802-
allChildren.add(an);
803-
allChildren.add(ac.getAccessibleRole());
804-
allChildren.add(String.valueOf((tree.isRootVisible() ? path.getPathCount() : path.getPathCount() - 1)));
805-
}
806-
}
807-
}
808-
}
809-
810-
return allChildren.toArray();
811-
}
812-
813752
ArrayList<Object> currentLevelChildren = new ArrayList<Object>();
814753
ArrayList<Accessible> parentStack = new ArrayList<Accessible>();
754+
HashMap<Accessible, List<Object>> childrenOfParent = new HashMap<>();
815755
parentStack.add(a);
816756
ArrayList<Integer> indexses = new ArrayList<Integer>();
817757
Integer index = 0;
818758
int currentLevel = level;
819759
while (!parentStack.isEmpty()) {
820760
Accessible p = parentStack.get(parentStack.size() - 1);
821-
822-
currentLevelChildren.addAll(Arrays.asList(getChildrenAndRolesImpl(p, c, JAVA_AX_ALL_CHILDREN, allowIgnored, ChildrenOperations.COMMON)));
761+
if (!childrenOfParent.containsKey(p)) {
762+
childrenOfParent.put(p, Arrays.asList(getChildrenAndRolesImpl(p,
763+
c, JAVA_AX_ALL_CHILDREN, allowIgnored,
764+
ChildrenOperations.COMMON)));
765+
}
766+
currentLevelChildren.addAll(childrenOfParent.get(p));
823767
if ((currentLevelChildren.size() == 0) || (index >= currentLevelChildren.size())) {
824768
if (!parentStack.isEmpty()) parentStack.remove(parentStack.size() - 1);
825769
if (!indexses.isEmpty()) index = indexses.remove(indexses.size() - 1);
@@ -862,7 +806,6 @@ public Object[] call() throws Exception {
862806
currentLevel += 1;
863807
continue;
864808
}
865-
866809
}
867810

868811
return allChildren.toArray();

src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineAccessibility.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
2-
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
3-
* Copyright (c) 2021, JetBrains s.r.o.. All rights reserved.
2+
* Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2021, 2024, JetBrains s.r.o.. All rights reserved.
44
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
55
*
66
* This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,12 @@
2929
// This is a tree representation. See: https://developer.apple.com/documentation/appkit/nsoutlineview
3030

3131
@interface OutlineAccessibility : ListAccessibility <NSAccessibilityOutline>
32-
32+
{
33+
NSMutableArray<id<NSAccessibilityRow>> *rowCache;
34+
BOOL rowCacheValid;
35+
NSMutableArray<id<NSAccessibilityRow>> *selectedRowCache;
36+
BOOL selectedRowCacheValid;
37+
}
3338
@property(readonly) BOOL isTreeRootVisible;
3439

3540
@end

src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/OutlineAccessibility.m

Lines changed: 86 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
2-
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
3-
* Copyright (c) 2021, JetBrains s.r.o.. All rights reserved.
2+
* Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2021, 2024, JetBrains s.r.o.. All rights reserved.
44
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
55
*
66
* This code is free software; you can redistribute it and/or modify it
@@ -55,4 +55,88 @@ - (NSString *)accessibilityLabel
5555
return [[super accessibilityLabel] isEqualToString:@"list"] ? @"tree" : [super accessibilityLabel];
5656
}
5757

58+
- (nullable NSArray<id<NSAccessibilityRow>> *)accessibilityRows
59+
{
60+
return [self accessibilityChildren];
61+
}
62+
63+
- (nullable NSArray<id<NSAccessibilityRow>> *)accessibilitySelectedRows
64+
{
65+
return [self accessibilitySelectedChildren];
66+
}
67+
68+
- (nullable NSArray<id<NSAccessibilityRow>> *)accessibilityChildren
69+
{
70+
if (![self isCacheValid]) {
71+
NSArray *t = [super accessibilityChildren];
72+
if (t != nil) {
73+
rowCache = [[NSMutableArray arrayWithArray:t] retain];
74+
} else {
75+
rowCache = nil;
76+
}
77+
rowCacheValid = YES;
78+
}
79+
return rowCache;
80+
}
81+
82+
- (nullable NSArray<id<NSAccessibilityRow>> *)accessibilitySelectedChildren
83+
{
84+
if (!selectedRowCacheValid) {
85+
NSArray *t = [super accessibilitySelectedChildren];
86+
if (t != nil) {
87+
selectedRowCache = [[NSMutableArray arrayWithArray:t] retain];
88+
} else {
89+
selectedRowCache = nil;
90+
}
91+
selectedRowCacheValid = YES;
92+
}
93+
return selectedRowCache;
94+
}
95+
96+
- (BOOL)isCacheValid
97+
{
98+
if (rowCacheValid && [[self parent] respondsToSelector:NSSelectorFromString(@"isCacheValid")]) {
99+
return [[self parent] isCacheValid];
100+
}
101+
return rowCacheValid;
102+
}
103+
104+
- (void)invalidateCache
105+
{
106+
rowCacheValid = NO;
107+
}
108+
109+
- (void)invalidateSelectionCache
110+
{
111+
selectedRowCacheValid = NO;
112+
}
113+
114+
- (void)postSelectionChanged
115+
{
116+
AWT_ASSERT_APPKIT_THREAD;
117+
[self invalidateSelectionCache];
118+
[super postSelectionChanged];
119+
}
120+
121+
- (void)postTreeNodeCollapsed
122+
{
123+
AWT_ASSERT_APPKIT_THREAD;
124+
[self invalidateCache];
125+
[super postTreeNodeCollapsed];
126+
}
127+
128+
- (void)postTreeNodeExpanded
129+
{
130+
AWT_ASSERT_APPKIT_THREAD;
131+
[self invalidateCache];
132+
[super postTreeNodeExpanded];
133+
}
134+
135+
- (void)postSelectedCellsChanged
136+
{
137+
AWT_ASSERT_APPKIT_THREAD;
138+
[self invalidateSelectionCache];
139+
[super postSelectedCellsChanged];
140+
}
141+
58142
@end

0 commit comments

Comments
 (0)