34
34
import java .awt .event .KeyEvent ;
35
35
import java .beans .PropertyChangeEvent ;
36
36
import java .beans .PropertyChangeListener ;
37
+ import java .lang .annotation .Native ;
37
38
import java .lang .reflect .InvocationTargetException ;
38
39
import java .util .ArrayList ;
39
40
import java .util .HashSet ;
40
41
import java .util .Set ;
41
42
import java .util .concurrent .Callable ;
43
+ import java .util .Arrays ;
42
44
43
45
import javax .accessibility .Accessible ;
44
46
import javax .accessibility .AccessibleAction ;
57
59
import javax .swing .JLabel ;
58
60
import javax .swing .JMenuItem ;
59
61
import javax .swing .JTextArea ;
62
+ import javax .swing .JList ;
63
+ import javax .swing .JTree ;
60
64
import javax .swing .KeyStroke ;
61
65
62
66
import sun .awt .AWTAccessor ;
@@ -116,12 +120,7 @@ public void propertyChange(final PropertyChangeEvent evt) {
116
120
private native void focusChanged ();
117
121
118
122
static <T > T invokeAndWait (final Callable <T > callable , final Component c ) {
119
- if (c != null ) {
120
- try {
121
- return LWCToolkit .invokeAndWait (callable , c );
122
- } catch (final Exception e ) { e .printStackTrace (); }
123
- }
124
- return null ;
123
+ return invokeAndWait (callable , c , null );
125
124
}
126
125
127
126
static <T > T invokeAndWait (final Callable <T > callable , final Component c , final T defValue ) {
@@ -551,6 +550,10 @@ public void run() {
551
550
if (pac == null ) return ;
552
551
AccessibleSelection as = pac .getAccessibleSelection ();
553
552
if (as == null ) return ;
553
+ if (parent instanceof JList ) {
554
+ ((JList ) parent ).setSelectedIndex (i );
555
+ return ;
556
+ }
554
557
as .addAccessibleSelection (i );
555
558
}
556
559
}, c );
@@ -651,77 +654,148 @@ public boolean[] call() throws Exception {
651
654
652
655
// Duplicated from JavaComponentAccessibility
653
656
// Note that values >=0 are indexes into the child array
654
- static final int JAVA_AX_ALL_CHILDREN = -1 ;
655
- static final int JAVA_AX_SELECTED_CHILDREN = -2 ;
656
- static final int JAVA_AX_VISIBLE_CHILDREN = -3 ;
657
+ @ Native static final int JAVA_AX_ALL_CHILDREN = -1 ;
658
+ @ Native static final int JAVA_AX_SELECTED_CHILDREN = -2 ;
659
+ @ Native static final int JAVA_AX_VISIBLE_CHILDREN = -3 ;
657
660
658
661
// Each child takes up two entries in the array: one for itself and one for its role
659
662
public static Object [] getChildrenAndRoles (final Accessible a , final Component c , final int whichChildren , final boolean allowIgnored ) {
660
663
if (a == null ) return null ;
661
664
return invokeAndWait (new Callable <Object []>() {
662
665
public Object [] call () throws Exception {
663
- ArrayList <Object > childrenAndRoles = new ArrayList <Object >();
664
- _addChildren (a , whichChildren , allowIgnored , childrenAndRoles );
665
-
666
- /* In the case of fetching a selection, need to check to see if
667
- * the active descendant is at the beginning of the list. If it
668
- * is not it needs to be moved to the beginning of the list so
669
- * VoiceOver will annouce it correctly. The list returned
670
- * from Java is always in order from top to bottom, but when shift
671
- * selecting downward (extending the list) or multi-selecting using
672
- * the VO keys control+option+command+return the active descendant
673
- * is not at the top of the list in the shift select down case and
674
- * may not be in the multi select case.
675
- */
676
- if (whichChildren == JAVA_AX_SELECTED_CHILDREN ) {
677
- if (!childrenAndRoles .isEmpty ()) {
678
- AccessibleContext activeDescendantAC =
679
- CAccessible .getActiveDescendant (a );
680
- if (activeDescendantAC != null ) {
681
- String activeDescendantName =
682
- activeDescendantAC .getAccessibleName ();
683
- AccessibleRole activeDescendantRole =
684
- activeDescendantAC .getAccessibleRole ();
685
- // Move active descendant to front of list.
686
- // List contains pairs of each selected item's
687
- // Accessible and AccessibleRole.
688
- ArrayList <Object > newArray = new ArrayList <Object >();
689
- int count = childrenAndRoles .size ();
690
- Accessible currentAccessible = null ;
691
- AccessibleContext currentAC = null ;
692
- String currentName = null ;
693
- AccessibleRole currentRole = null ;
694
- for (int i = 0 ; i < count ; i +=2 ) {
695
- // Is this the active descendant?
696
- currentAccessible = (Accessible )childrenAndRoles .get (i );
697
- currentAC = currentAccessible .getAccessibleContext ();
698
- currentName = currentAC .getAccessibleName ();
699
- currentRole = (AccessibleRole )childrenAndRoles .get (i +1 );
700
- if (currentName != null && currentName .equals (activeDescendantName ) &&
701
- currentRole .equals (activeDescendantRole ) ) {
702
- newArray .add (0 , currentAccessible );
703
- newArray .add (1 , currentRole );
704
- } else {
705
- newArray .add (currentAccessible );
706
- newArray .add (currentRole );
707
- }
708
- }
709
- childrenAndRoles = newArray ;
666
+ return getChildrenAndRolesImpl (a , c , whichChildren , allowIgnored );
667
+ }
668
+ }, c );
669
+ }
670
+
671
+ private static Object [] getChildrenAndRolesImpl (final Accessible a , final Component c , final int whichChildren , final boolean allowIgnored ) {
672
+ if (a == null ) return null ;
673
+
674
+ ArrayList <Object > childrenAndRoles = new ArrayList <Object >();
675
+ _addChildren (a , whichChildren , allowIgnored , childrenAndRoles );
676
+
677
+ /* In case of fetching a selection, we need to check if
678
+ * the active descendant is at the beginning of the list, or
679
+ * otherwise move it, so that VoiceOver announces it correctly.
680
+ * The java list is always in order from top to bottom, but when
681
+ * (1) shift-selecting downward (extending the list) or (2) multi-selecting with
682
+ * the VO keys (CTRL+ALT+CMD+RETURN) the active descendant
683
+ * is not at the top of the list in the 1st case and may not be in the 2nd.
684
+ */
685
+ if (whichChildren == JAVA_AX_SELECTED_CHILDREN ) {
686
+ if (!childrenAndRoles .isEmpty ()) {
687
+ AccessibleContext activeDescendantAC =
688
+ CAccessible .getActiveDescendant (a );
689
+ if (activeDescendantAC != null ) {
690
+ String activeDescendantName =
691
+ activeDescendantAC .getAccessibleName ();
692
+ AccessibleRole activeDescendantRole =
693
+ activeDescendantAC .getAccessibleRole ();
694
+ // Move active descendant to front of list.
695
+ // List contains pairs of each selected item's
696
+ // Accessible and AccessibleRole.
697
+ ArrayList <Object > newArray = new ArrayList <Object >();
698
+ int count = childrenAndRoles .size ();
699
+ Accessible currentAccessible = null ;
700
+ AccessibleContext currentAC = null ;
701
+ String currentName = null ;
702
+ AccessibleRole currentRole = null ;
703
+ for (int i = 0 ; i < count ; i += 2 ) {
704
+ // Is this the active descendant?
705
+ currentAccessible = (Accessible ) childrenAndRoles .get (i );
706
+ currentAC = currentAccessible .getAccessibleContext ();
707
+ currentName = currentAC .getAccessibleName ();
708
+ currentRole = (AccessibleRole ) childrenAndRoles .get (i + 1 );
709
+ if (currentName != null && currentName .equals (activeDescendantName ) &&
710
+ currentRole .equals (activeDescendantRole )) {
711
+ newArray .add (0 , currentAccessible );
712
+ newArray .add (1 , currentRole );
713
+ } else {
714
+ newArray .add (currentAccessible );
715
+ newArray .add (currentRole );
710
716
}
711
717
}
718
+ childrenAndRoles = newArray ;
712
719
}
720
+ }
721
+ }
722
+
723
+ if ((whichChildren < 0 ) || (whichChildren * 2 >= childrenAndRoles .size ())) {
724
+ return childrenAndRoles .toArray ();
725
+ }
726
+
727
+ return new Object []{childrenAndRoles .get (whichChildren * 2 ), childrenAndRoles .get ((whichChildren * 2 ) + 1 )};
728
+ }
729
+
730
+ // This method is called from the native
731
+ // Each child takes up three entries in the array: one for itself, one for its role, and one for the recursion level
732
+ private static Object [] getChildrenAndRolesRecursive (final Accessible a , final Component c , final int whichChildren , final boolean allowIgnored , final int level ) {
733
+ if (a == null ) return null ;
734
+ return invokeAndWait (new Callable <Object []>() {
735
+ public Object [] call () throws Exception {
736
+ ArrayList <Object > currentLevelChildren = new ArrayList <Object >();
737
+ ArrayList <Object > allChildren = new ArrayList <Object >();
738
+ ArrayList <Accessible > parentStack = new ArrayList <Accessible >();
739
+ parentStack .add (a );
740
+ ArrayList <Integer > indexses = new ArrayList <Integer >();
741
+ Integer index = 0 ;
742
+ int currentLevel = level ;
743
+ while (!parentStack .isEmpty ()) {
744
+ Accessible p = parentStack .get (parentStack .size () - 1 );
745
+
746
+ currentLevelChildren .addAll (Arrays .asList (getChildrenAndRolesImpl (p , c , JAVA_AX_ALL_CHILDREN , allowIgnored )));
747
+ if ((currentLevelChildren .size () == 0 ) || (index >= currentLevelChildren .size ())) {
748
+ if (!parentStack .isEmpty ()) parentStack .remove (parentStack .size () - 1 );
749
+ if (!indexses .isEmpty ()) index = indexses .remove (indexses .size () - 1 );
750
+ currentLevel -= 1 ;
751
+ currentLevelChildren .clear ();
752
+ continue ;
753
+ }
754
+
755
+ Accessible ca = null ;
756
+ Object obj = currentLevelChildren .get (index );
757
+ if (!(obj instanceof Accessible )) {
758
+ index += 2 ;
759
+ currentLevelChildren .clear ();
760
+ continue ;
761
+ }
762
+ ca = (Accessible ) obj ;
763
+ Object role = currentLevelChildren .get (index + 1 );
764
+ currentLevelChildren .clear ();
765
+
766
+ AccessibleContext cac = ca .getAccessibleContext ();
767
+ if (cac == null ) {
768
+ index += 2 ;
769
+ continue ;
770
+ }
771
+
772
+ if ((cac .getAccessibleStateSet ().contains (AccessibleState .SELECTED ) && (whichChildren == JAVA_AX_SELECTED_CHILDREN )) ||
773
+ (cac .getAccessibleStateSet ().contains (AccessibleState .VISIBLE ) && (whichChildren == JAVA_AX_VISIBLE_CHILDREN )) ||
774
+ (whichChildren == JAVA_AX_ALL_CHILDREN )) {
775
+ allChildren .add (ca );
776
+ allChildren .add (role );
777
+ allChildren .add (String .valueOf (currentLevel ));
778
+ }
779
+
780
+ index += 2 ;
781
+
782
+ if (cac .getAccessibleStateSet ().contains (AccessibleState .EXPANDED )) {
783
+ parentStack .add (ca );
784
+ indexses .add (index );
785
+ index = 0 ;
786
+ currentLevel += 1 ;
787
+ continue ;
788
+ }
713
789
714
- if ((whichChildren < 0 ) || (whichChildren * 2 >= childrenAndRoles .size ())) {
715
- return childrenAndRoles .toArray ();
716
790
}
717
791
718
- return new Object [] { childrenAndRoles . get ( whichChildren * 2 ), childrenAndRoles . get (( whichChildren * 2 ) + 1 ) } ;
792
+ return allChildren . toArray () ;
719
793
}
720
794
}, c );
721
795
}
722
796
723
- private static final int JAVA_AX_ROWS = 1 ;
724
- private static final int JAVA_AX_COLS = 2 ;
797
+ @ Native private static final int JAVA_AX_ROWS = 1 ;
798
+ @ Native private static final int JAVA_AX_COLS = 2 ;
725
799
726
800
public static int getTableInfo (final Accessible a , final Component c ,
727
801
final int info ) {
@@ -740,6 +814,23 @@ public static int getTableInfo(final Accessible a, final Component c,
740
814
}, c );
741
815
}
742
816
817
+ private static int [] getTableSelectedInfo (final Accessible a , final Component c ,
818
+ final int info ) {
819
+ if (a == null ) return null ;
820
+ return invokeAndWait (() -> {
821
+ AccessibleContext ac = a .getAccessibleContext ();
822
+ AccessibleTable table = ac .getAccessibleTable ();
823
+ if (table != null ) {
824
+ if (info == JAVA_AX_COLS ) {
825
+ return table .getSelectedAccessibleColumns ();
826
+ } else if (info == JAVA_AX_ROWS ) {
827
+ return table .getSelectedAccessibleRows ();
828
+ }
829
+ }
830
+ return null ;
831
+ }, c );
832
+ }
833
+
743
834
private static AccessibleRole getAccessibleRoleForLabel (JLabel l , AccessibleRole fallback ) {
744
835
String text = l .getText ();
745
836
if (text != null && text .length () > 0 ) {
@@ -858,4 +949,18 @@ public Long call() throws Exception {
858
949
}
859
950
}, (Component )ax );
860
951
}
952
+
953
+ private static boolean isTreeRootVisible (Accessible a , Component c ) {
954
+ if (a == null ) return false ;
955
+
956
+ return invokeAndWait (new Callable <Boolean >() {
957
+ public Boolean call () throws Exception {
958
+ Accessible sa = CAccessible .getSwingAccessible (a );
959
+ if (sa instanceof JTree ) {
960
+ return ((JTree ) sa ).isRootVisible ();
961
+ }
962
+ return false ;
963
+ }
964
+ }, c );
965
+ }
861
966
}
1 commit comments
openjdk-notifier[bot] commentedon Nov 16, 2021
Review
Issues