Skip to content

Commit 05f13e7

Browse files
author
Alexander Zuev
committedMay 25, 2024
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

+10-67
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

+8-3
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

+86-2
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

3 commit comments

Comments
 (3)

openjdk-notifier[bot] commented on May 25, 2024

@openjdk-notifier[bot]

GoeLin commented on Sep 10, 2024

@GoeLin
Member

/backport jdk21u

openjdk[bot] commented on Sep 10, 2024

@openjdk[bot]

@GoeLin the backport was successfully created on the branch backport-GoeLin-05f13e75-master in my personal fork of openjdk/jdk21u. To create a pull request with this backport targeting openjdk/jdk21u:master, just click the following link:

➡️ Create pull request

The title of the pull request is automatically filled in correctly and below you find a suggestion for the pull request body:

Hi all,

This pull request contains a backport of commit 05f13e75 from the openjdk/jdk repository.

The commit being backported was authored by Alexander Zuev on 25 May 2024 and was reviewed by Artem Semenov, Abhishek Kumar and Prasanta Sadhukhan.

Thanks!

If you need to update the source branch of the pull then run the following commands in a local clone of your personal fork of openjdk/jdk21u:

$ git fetch https://github.com/openjdk-bots/jdk21u.git backport-GoeLin-05f13e75-master:backport-GoeLin-05f13e75-master
$ git checkout backport-GoeLin-05f13e75-master
# make changes
$ git add paths/to/changed/files
$ git commit --message 'Describe additional changes made'
$ git push https://github.com/openjdk-bots/jdk21u.git backport-GoeLin-05f13e75-master
Please sign in to comment.