Skip to content

Commit 05f13e7

Browse files
author
Alexander Zuev
committed
8329667: [macos] Issue with JTree related fix for JDK-8317771
Reviewed-by: asemenov, abhiscxk, psadhukhan
1 parent 7bf1989 commit 05f13e7

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, 2022, 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
@@ -36,10 +36,11 @@
3636
import java.beans.PropertyChangeEvent;
3737
import java.beans.PropertyChangeListener;
3838
import java.lang.annotation.Native;
39-
import java.lang.reflect.Constructor;
4039
import java.lang.reflect.InvocationTargetException;
4140
import java.util.ArrayList;
41+
import java.util.HashMap;
4242
import java.util.HashSet;
43+
import java.util.List;
4344
import java.util.Set;
4445
import java.util.concurrent.Callable;
4546
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;
@@ -759,84 +759,28 @@ private static Object[] getChildrenAndRolesImpl(Accessible a, Component c, int w
759759
return new Object[]{childrenAndRoles.get(whichChildren * 2), childrenAndRoles.get((whichChildren * 2) + 1)};
760760
}
761761

762-
private static Accessible createAccessibleTreeNode(JTree t, TreePath p) {
763-
Accessible a = null;
764-
765-
try {
766-
Class<?> accessibleJTreeNodeClass = Class.forName("javax.swing.JTree$AccessibleJTree$AccessibleJTreeNode");
767-
Constructor<?> constructor = accessibleJTreeNodeClass.getConstructor(t.getAccessibleContext().getClass(), JTree.class, TreePath.class, Accessible.class);
768-
constructor.setAccessible(true);
769-
a = ((Accessible) constructor.newInstance(t.getAccessibleContext(), t, p, null));
770-
} catch (Exception e) {
771-
e.printStackTrace();
772-
}
773-
774-
return a;
775-
}
776-
777762
// This method is called from the native
778763
// Each child takes up three entries in the array: one for itself, one for its role, and one for the recursion level
779764
private static Object[] getChildrenAndRolesRecursive(final Accessible a, final Component c, final int whichChildren, final boolean allowIgnored, final int level) {
780765
if (a == null) return null;
781766
return invokeAndWait(new Callable<Object[]>() {
782767
public Object[] call() throws Exception {
783768
ArrayList<Object> allChildren = new ArrayList<Object>();
784-
785-
Accessible at = null;
786-
if (a instanceof CAccessible) {
787-
at = CAccessible.getSwingAccessible(a);
788-
} else {
789-
at = a;
790-
}
791-
792-
if (at instanceof JTree) {
793-
JTree tree = ((JTree) at);
794-
795-
if (whichChildren == JAVA_AX_ALL_CHILDREN) {
796-
int count = tree.getRowCount();
797-
for (int i = 0; i < count; i++) {
798-
TreePath path = tree.getPathForRow(i);
799-
Accessible an = createAccessibleTreeNode(tree, path);
800-
if (an != null) {
801-
AccessibleContext ac = an.getAccessibleContext();
802-
if (ac != null) {
803-
allChildren.add(an);
804-
allChildren.add(ac.getAccessibleRole());;
805-
allChildren.add(String.valueOf((tree.isRootVisible() ? path.getPathCount() : path.getPathCount() - 1)));
806-
}
807-
}
808-
}
809-
}
810-
811-
if (whichChildren == JAVA_AX_SELECTED_CHILDREN) {
812-
int count = tree.getSelectionCount();
813-
for (int i = 0; i < count; i++) {
814-
TreePath path = tree.getSelectionPaths()[i];
815-
Accessible an = createAccessibleTreeNode(tree, path);
816-
if (an != null) {
817-
AccessibleContext ac = an.getAccessibleContext();
818-
if (ac != null) {
819-
allChildren.add(an);
820-
allChildren.add(ac.getAccessibleRole());
821-
allChildren.add(String.valueOf((tree.isRootVisible() ? path.getPathCount() : path.getPathCount() - 1)));
822-
}
823-
}
824-
}
825-
}
826-
827-
return allChildren.toArray();
828-
}
829-
830769
ArrayList<Object> currentLevelChildren = new ArrayList<Object>();
831770
ArrayList<Accessible> parentStack = new ArrayList<Accessible>();
771+
HashMap<Accessible, List<Object>> childrenOfParent = new HashMap<>();
832772
parentStack.add(a);
833773
ArrayList<Integer> indexses = new ArrayList<Integer>();
834774
Integer index = 0;
835775
int currentLevel = level;
836776
while (!parentStack.isEmpty()) {
837777
Accessible p = parentStack.get(parentStack.size() - 1);
838-
839-
currentLevelChildren.addAll(Arrays.asList(getChildrenAndRolesImpl(p, c, JAVA_AX_ALL_CHILDREN, allowIgnored, ChildrenOperations.COMMON)));
778+
if (!childrenOfParent.containsKey(p)) {
779+
childrenOfParent.put(p, Arrays.asList(getChildrenAndRolesImpl(p,
780+
c, JAVA_AX_ALL_CHILDREN, allowIgnored,
781+
ChildrenOperations.COMMON)));
782+
}
783+
currentLevelChildren.addAll(childrenOfParent.get(p));
840784
if ((currentLevelChildren.size() == 0) || (index >= currentLevelChildren.size())) {
841785
if (!parentStack.isEmpty()) parentStack.remove(parentStack.size() - 1);
842786
if (!indexses.isEmpty()) index = indexses.remove(indexses.size() - 1);
@@ -879,7 +823,6 @@ public Object[] call() throws Exception {
879823
currentLevel += 1;
880824
continue;
881825
}
882-
883826
}
884827

885828
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)