src/macosx/native/sun/awt/JavaComponentAccessibility.m

Print this page




  49 
  50 // these constants are duplicated in CAccessibility.java
  51 #define JAVA_AX_ALL_CHILDREN (-1)
  52 #define JAVA_AX_SELECTED_CHILDREN (-2)
  53 #define JAVA_AX_VISIBLE_CHILDREN (-3)
  54 // If the value is >=0, it's an index
  55 
  56 static JNF_STATIC_MEMBER_CACHE(jm_getChildrenAndRoles, sjc_CAccessibility, "getChildrenAndRoles", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;IZ)[Ljava/lang/Object;");
  57 static JNF_STATIC_MEMBER_CACHE(sjm_getAccessibleComponent, sjc_CAccessibility, "getAccessibleComponent", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljavax/accessibility/AccessibleComponent;");
  58 static JNF_STATIC_MEMBER_CACHE(sjm_getAccessibleValue, sjc_CAccessibility, "getAccessibleValue", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljavax/accessibility/AccessibleValue;");
  59 static JNF_STATIC_MEMBER_CACHE(sjm_getAccessibleName, sjc_CAccessibility, "getAccessibleName", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljava/lang/String;");
  60 static JNF_STATIC_MEMBER_CACHE(sjm_getAccessibleDescription, sjc_CAccessibility, "getAccessibleDescription", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljava/lang/String;");
  61 static JNF_STATIC_MEMBER_CACHE(sjm_isFocusTraversable, sjc_CAccessibility, "isFocusTraversable", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Z");
  62 static JNF_STATIC_MEMBER_CACHE(sjm_getAccessibleIndexInParent, sjc_CAccessibility, "getAccessibleIndexInParent", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)I");
  63 
  64 static JNF_CLASS_CACHE(sjc_CAccessible, "sun/lwawt/macosx/CAccessible");
  65 
  66 static JNF_MEMBER_CACHE(jf_ptr, sjc_CAccessible, "ptr", "J");
  67 static JNF_STATIC_MEMBER_CACHE(sjm_getCAccessible, sjc_CAccessible, "getCAccessible", "(Ljavax/accessibility/Accessible;)Lsun/lwawt/macosx/CAccessible;");
  68 
  69 
  70 static jobject sAccessibilityClass = NULL;
  71 
  72 // sAttributeNamesForRoleCache holds the names of the attributes to which each java
  73 // AccessibleRole responds (see AccessibleRole.java).
  74 // This cache is queried before attempting to access a given attribute for a particular role.
  75 static NSMutableDictionary *sAttributeNamesForRoleCache = nil;
  76 static NSObject *sAttributeNamesLOCK = nil;
  77 
  78 @interface TabGroupAccessibility : JavaComponentAccessibility {
  79     NSInteger _numTabs;
  80 }
  81 
  82 - (id)currentTabWithEnv:(JNIEnv *)env withAxContext:(jobject)axContext;
  83 - (NSArray *)tabControlsWithEnv:(JNIEnv *)env withTabGroupAxContext:(jobject)axContext withTabCode:(NSInteger)whichTabs allowIgnored:(BOOL)allowIgnored;
  84 - (NSArray *)contentsWithEnv:(JNIEnv *)env withTabGroupAxContext:(jobject)axContext withTabCode:(NSInteger)whichTabs allowIgnored:(BOOL)allowIgnored;
  85 - (NSArray *)initializeAttributeNamesWithEnv:(JNIEnv *)env;
  86 
  87 - (NSArray *)accessibilityArrayAttributeValues:(NSString *)attribute index:(NSUInteger)index maxCount:(NSUInteger)maxCount;
  88 - (NSArray *)accessibilityChildrenAttribute;
  89 - (id) accessibilityTabsAttribute;


 196 }
 197 
 198 - (void)postValueChanged
 199 {
 200     AWT_ASSERT_APPKIT_THREAD;
 201     NSAccessibilityPostNotification(self, NSAccessibilityValueChangedNotification);
 202 }
 203 
 204 - (void)postSelectedTextChanged
 205 {
 206     AWT_ASSERT_APPKIT_THREAD;
 207     NSAccessibilityPostNotification(self, NSAccessibilitySelectedTextChangedNotification);
 208 }
 209 
 210 - (void)postSelectionChanged
 211 {
 212     AWT_ASSERT_APPKIT_THREAD;
 213     NSAccessibilityPostNotification(self, NSAccessibilitySelectedChildrenChangedNotification);
 214 }
 215 


















 216 - (BOOL)isEqual:(id)anObject
 217 {
 218     if (![anObject isKindOfClass:[self class]]) return NO;
 219     JavaComponentAccessibility *accessibility = (JavaComponentAccessibility *)anObject;
 220 
 221     JNIEnv* env = [ThreadUtilities getJNIEnv];
 222     return (*env)->IsSameObject(env, accessibility->fAccessible, fAccessible);
 223 }
 224 
 225 - (BOOL)isAccessibleWithEnv:(JNIEnv *)env forAccessible:(jobject)accessible
 226 {
 227     return (*env)->IsSameObject(env, fAccessible, accessible);
 228 }
 229 
 230 + (void)initialize
 231 {
 232     if (sAttributeNamesForRoleCache == nil) {
 233         sAttributeNamesLOCK = [[NSObject alloc] init];
 234         sAttributeNamesForRoleCache = [[NSMutableDictionary alloc] initWithCapacity:60];
 235     }


 261         NSInteger i;
 262         for (i = 0; i < count; i++) {
 263             jstring jString = JNFNSToJavaString(env, [ignoredKeys objectAtIndex:i]);
 264             (*env)->SetObjectArrayElement(env, result, i, jString);
 265             (*env)->DeleteLocalRef(env, jString);
 266         }
 267 
 268         sAccessibilityClass = JNFCallStaticObjectMethod(env, jm_getAccessibility, result); // AWT_THREADING Safe (known object)
 269     }
 270 }
 271 
 272 + (void)postFocusChanged:(id)message
 273 {
 274     AWT_ASSERT_APPKIT_THREAD;
 275     NSAccessibilityPostNotification([NSApp accessibilityFocusedUIElement], NSAccessibilityFocusedUIElementChangedNotification);
 276 }
 277 
 278 + (jobject) getCAccessible:(jobject)jaccessible withEnv:(JNIEnv *)env {
 279     if (JNFIsInstanceOf(env, jaccessible, &sjc_CAccessible)) {
 280         return jaccessible;
 281     }
 282     else if (JNFIsInstanceOf(env, jaccessible, &sjc_Accessible)) {
 283         return JNFCallStaticObjectMethod(env, sjm_getCAccessible, jaccessible);
 284     }
 285     return NULL;
 286 }
 287 
 288 + (NSArray *)childrenOfParent:(JavaComponentAccessibility *)parent withEnv:(JNIEnv *)env withChildrenCode:(NSInteger)whichChildren allowIgnored:(BOOL)allowIgnored
 289 {
 290     if (parent->fAccessible == NULL) return nil;
 291     jobjectArray jchildrenAndRoles = (jobjectArray)JNFCallStaticObjectMethod(env, jm_getChildrenAndRoles, parent->fAccessible, parent->fComponent, whichChildren, allowIgnored); // AWT_THREADING Safe (AWTRunLoop)
 292     if (jchildrenAndRoles == NULL) return nil;
 293 
 294     jsize arrayLen = (*env)->GetArrayLength(env, jchildrenAndRoles);
 295     NSMutableArray *children = [NSMutableArray arrayWithCapacity:arrayLen/2]; //childrenAndRoles array contains two elements (child, role) for each child
 296 
 297     NSInteger i;
 298     NSUInteger childIndex = (whichChildren >= 0) ? whichChildren : 0; // if we're getting one particular child, make sure to set its index correctly
 299     for(i = 0; i < arrayLen; i+=2)
 300     {
 301         jobject /* Accessible */ jchild = (*env)->GetObjectArrayElement(env, jchildrenAndRoles, i);
 302         jobject /* String */ jchildJavaRole = (*env)->GetObjectArrayElement(env, jchildrenAndRoles, i+1);


 351     }
 352 
 353     // otherwise, create a new instance
 354     JavaComponentAccessibility *newChild = nil;
 355     if ([javaRole isEqualToString:@"pagetablist"]) {
 356         newChild = [TabGroupAccessibility alloc];
 357     } else if ([javaRole isEqualToString:@"scrollpane"]) {
 358         newChild = [ScrollAreaAccessibility alloc];
 359     } else {
 360         NSString *nsRole = [sRoles objectForKey:javaRole];
 361         if ([nsRole isEqualToString:NSAccessibilityStaticTextRole] || [nsRole isEqualToString:NSAccessibilityTextAreaRole] || [nsRole isEqualToString:NSAccessibilityTextFieldRole]) {
 362             newChild = [JavaTextAccessibility alloc];
 363         } else {
 364             newChild = [JavaComponentAccessibility alloc];
 365         }
 366     }
 367 
 368     // must init freshly -alloc'd object
 369     [newChild initWithParent:parent withEnv:env withAccessible:jCAX withIndex:index withView:view withJavaRole:javaRole]; // must init new instance
 370 








 371     // must hard retain pointer poked into Java object
 372     [newChild retain];
 373     JNFSetLongField(env, jCAX, jf_ptr, ptr_to_jlong(newChild));
 374     (*env)->DeleteLocalRef(env, jCAX);
 375 
 376     // return autoreleased instance
 377     return [newChild autorelease];
 378 }
 379 
 380 - (NSArray *)initializeAttributeNamesWithEnv:(JNIEnv *)env
 381 {
 382     static JNF_STATIC_MEMBER_CACHE(jm_getInitialAttributeStates, sjc_CAccessibility, "getInitialAttributeStates", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)[Z");
 383 
 384     NSMutableArray *attributeNames = [NSMutableArray arrayWithCapacity:20];
 385     [attributeNames retain];
 386 
 387     // all elements respond to parent, role, role description, window, topLevelUIElement, help
 388     [attributeNames addObject:NSAccessibilityParentAttribute];
 389     [attributeNames addObject:NSAccessibilityRoleAttribute];
 390     [attributeNames addObject:NSAccessibilityRoleDescriptionAttribute];


 617             names = [self initializeAttributeNamesWithEnv:env];
 618 #ifdef JAVA_AX_DEBUG
 619             NSLog(@"Initializing: %s for %@: %@", __FUNCTION__, javaRole, names);
 620 #endif
 621             [sAttributeNamesForRoleCache setObject:names forKey:javaRole];
 622         }
 623         // The above set of attributes is immutable per role, but some objects, if
 624         // they are the child of a list, need to add the selected and index attributes.
 625         id myParent = [self accessibilityParentAttribute];
 626         if ([myParent isKindOfClass:[JavaComponentAccessibility class]]) {
 627             NSString *parentRole = [(JavaComponentAccessibility *)myParent javaRole];
 628             if ([parentRole isEqualToString:@"list"]) {
 629                 NSMutableArray *moreNames =
 630                     [[NSMutableArray alloc] initWithCapacity: [names count] + 2];
 631                 [moreNames addObjectsFromArray: names];
 632                 [moreNames addObject:NSAccessibilitySelectedAttribute];
 633                 [moreNames addObject:NSAccessibilityIndexAttribute];
 634                 return moreNames;
 635             }
 636         }









 637         return names;
 638 
 639     }  // end @synchronized
 640 
 641 #ifdef JAVA_AX_DEBUG
 642     NSLog(@"Warning in %s: could not find attribute names for role: %@", __FUNCTION__, [self javaRole]);
 643 #endif
 644 
 645     return nil;
 646 }
 647 
 648 // -- accessibility attributes --
 649 
 650 - (BOOL)accessibilityShouldUseUniqueId {
 651     return YES;
 652 }
 653 
 654 - (BOOL)accessibilitySupportsOverriddenAttributes {
 655     return YES;
 656 }


 690 
 691 // specific attributes, in alphabetical order a la
 692 // http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/ObjC_classic/Protocols/NSAccessibility.html
 693 
 694 // Elements that current element contains (NSArray)
 695 - (NSArray *)accessibilityChildrenAttribute
 696 {
 697     JNIEnv* env = [ThreadUtilities getJNIEnv];
 698     NSArray *children = [JavaComponentAccessibility childrenOfParent:self
 699                                                     withEnv:env
 700                                                     withChildrenCode:JAVA_AX_ALL_CHILDREN
 701                                                     allowIgnored:NO];
 702 
 703     NSArray *value = nil;
 704     if ([children count] > 0) {
 705         value = children;
 706     }
 707 
 708     return value;
 709 }

 710 - (BOOL)accessibilityIsChildrenAttributeSettable
 711 {
 712     return NO;
 713 }
 714 
 715 - (NSUInteger)accessibilityIndexOfChild:(id)child
 716 {
 717     // Only special-casing for Lists, for now. This allows lists to be accessible, fixing radr://3856139 "JLists are broken".
 718     // Will probably want to special-case for Tables when we implement them (radr://3096643 "Accessibility: Table").
 719     // In AppKit, NSMatrixAccessibility (which uses NSAccessibilityListRole), NSTableRowAccessibility, and NSTableViewAccessibility are the
 720     // only ones that override the default implementation in NSAccessibility
 721     if (![[self accessibilityRoleAttribute] isEqualToString:NSAccessibilityListRole]) {
 722         return [super accessibilityIndexOfChild:child];
 723     }
 724 
 725     jint returnValue =
 726         JNFCallStaticIntMethod( [ThreadUtilities getJNIEnv],
 727                                 sjm_getAccessibleIndexInParent,
 728                                 ((JavaComponentAccessibility *)child)->fAccessible,
 729                                 ((JavaComponentAccessibility *)child)->fComponent );


 922     // Now make it into Cocoa screen coords.
 923     point.y = [[[[self view] window] screen] frame].size.height - point.y;
 924 
 925     return [NSValue valueWithPoint:point];
 926 }
 927 
 928 - (BOOL)accessibilityIsPositionAttributeSettable
 929 {
 930     // In AppKit, position is only settable for a window (NSAccessibilityWindowRole). Our windows are taken care of natively, so we don't need to deal with this here
 931     // We *could* make use of Java's AccessibleComponent.setLocation() method. Investigate. radr://3953869
 932     return NO;
 933 }
 934 
 935 // Element type, such as NSAccessibilityRadioButtonRole (NSString). See the role table
 936 // at http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/ObjC_classic/Protocols/NSAccessibility.html
 937 - (NSString *)accessibilityRoleAttribute
 938 {
 939     if (fNSRole == nil) {
 940         NSString *javaRole = [self javaRole];
 941         fNSRole = [sRoles objectForKey:javaRole];







 942         if (fNSRole == nil) {
 943             // this component has assigned itself a custom AccessibleRole not in the sRoles array
 944             fNSRole = javaRole;
 945         }
 946         [fNSRole retain];
 947     }
 948     return fNSRole;
 949 }

 950 - (BOOL)accessibilityIsRoleAttributeSettable
 951 {
 952     return NO;
 953 }
 954 
 955 // Localized, user-readable description of role, such as radio button (NSString)
 956 - (NSString *)accessibilityRoleDescriptionAttribute
 957 {
 958     // first ask AppKit for its accessible role description for a given AXRole
 959     NSString *value = NSAccessibilityRoleDescription([self accessibilityRoleAttribute], nil);
 960 
 961     if (value == nil) {
 962         // query java if necessary
 963         static JNF_STATIC_MEMBER_CACHE(jm_getAccessibleRoleDisplayString, sjc_CAccessibility, "getAccessibleRoleDisplayString", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljava/lang/String;");
 964 
 965         JNIEnv* env = [ThreadUtilities getJNIEnv];
 966 
 967         jobject axRole = JNFCallStaticObjectMethod(env, jm_getAccessibleRoleDisplayString, fAccessible, fComponent);
 968         if (axRole != NULL) {
 969             value = JNFJavaToNSString(env, axRole);


1029 - (NSValue *)accessibilitySizeAttribute {
1030     JNIEnv* env = [ThreadUtilities getJNIEnv];
1031     jobject axComponent = JNFCallStaticObjectMethod(env, sjm_getAccessibleComponent, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
1032     NSValue* size = [NSValue valueWithSize:getAxComponentSize(env, axComponent, fComponent)];
1033     (*env)->DeleteLocalRef(env, axComponent);
1034     return size;
1035 }
1036 
1037 - (BOOL)accessibilityIsSizeAttributeSettable
1038 {
1039     // SIZE is settable in windows if [self styleMask] & NSResizableWindowMask - but windows are heavyweight so we're ok here
1040     // SIZE is settable in columns if [[self tableValue] allowsColumnResizing - haven't dealt with columns yet
1041     return NO;
1042 }
1043 
1044 // Element subrole type, such as NSAccessibilityTableRowSubrole (NSString). See the subrole attribute table at
1045 // http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/ObjC_classic/Protocols/NSAccessibility.html
1046 - (NSString *)accessibilitySubroleAttribute
1047 {
1048     NSString *value = nil;
1049     if ([[self javaRole] isEqualToString:@"passwordtext"])
1050     {
1051         value = NSAccessibilitySecureTextFieldSubrole;
1052     }
1053     /*
1054     // other subroles. TableRow and OutlineRow may be relevant to us
1055      NSAccessibilityCloseButtonSubrole // no, heavyweight window takes care of this
1056      NSAccessibilityMinimizeButtonSubrole // "
1057      NSAccessibilityOutlineRowSubrole    // maybe?
1058      NSAccessibilitySecureTextFieldSubrole // currently used
1059      NSAccessibilityTableRowSubrole        // maybe?
1060      NSAccessibilityToolbarButtonSubrole // maybe?
1061      NSAccessibilityUnknownSubrole
1062      NSAccessibilityZoomButtonSubrole    // no, heavyweight window takes care of this
1063      NSAccessibilityStandardWindowSubrole// no, heavyweight window takes care of this
1064      NSAccessibilityDialogSubrole        // maybe?
1065      NSAccessibilitySystemDialogSubrole    // no
1066      NSAccessibilityFloatingWindowSubrole // in 1.5 if we implement these, heavyweight will take care of them anyway
1067      NSAccessibilitySystemFloatingWindowSubrole
1068      NSAccessibilityIncrementArrowSubrole  // no
1069      NSAccessibilityDecrementArrowSubrole  // no
1070      NSAccessibilityIncrementPageSubrole   // no


1106 - (NSWindow *)accessibilityTopLevelUIElementAttribute
1107 {
1108     return [self window];
1109 }
1110 
1111 - (BOOL)accessibilityIsTopLevelUIElementAttributeSettable
1112 {
1113     return NO;
1114 }
1115 
1116 // Element's value (id)
1117 // note that the appKit meaning of "accessibilityValue" is different from the java
1118 // meaning of "accessibleValue", which is specific to numerical values
1119 // (http://java.sun.com/j2se/1.3/docs/api/javax/accessibility/AccessibleValue.html#setCurrentAccessibleValue(java.lang.Number))
1120 - (id)accessibilityValueAttribute
1121 {
1122     static JNF_STATIC_MEMBER_CACHE(jm_getCurrentAccessibleValue, sjc_CAccessibility, "getCurrentAccessibleValue", "(Ljavax/accessibility/AccessibleValue;Ljava/awt/Component;)Ljava/lang/Number;");
1123 
1124     JNIEnv* env = [ThreadUtilities getJNIEnv];
1125 







































1126     // ask Java for the component's accessibleValue. In java, the "accessibleValue" just means a numerical value
1127     // a text value is taken care of in JavaTextAccessibility
1128 
1129     // cmcnote should coalesce these calls into one java call
1130     NSNumber *num = nil;
1131     jobject axValue = JNFCallStaticObjectMethod(env, sjm_getAccessibleValue, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
1132     if (axValue != NULL) {
1133         jobject str = JNFCallStaticObjectMethod(env, jm_getCurrentAccessibleValue, axValue, fComponent);
1134         if (str != NULL) {
1135             num = JNFJavaToNSNumber(env, str); // AWT_THREADING Safe (AWTRunLoop)
1136             (*env)->DeleteLocalRef(env, str);
1137         }
1138         (*env)->DeleteLocalRef(env, axValue);
1139     }
1140     if (num == nil) {
1141         num = [NSNumber numberWithInt:0];
1142     }
1143     return num;
1144 }
1145 


1323 (JNIEnv *env, jclass jklass, jlong element)
1324 {
1325 JNF_COCOA_ENTER(env);
1326     [ThreadUtilities performOnMainThread:@selector(postSelectedTextChanged)
1327                      on:(JavaComponentAccessibility *)jlong_to_ptr(element)
1328                      withObject:nil
1329                      waitUntilDone:NO];
1330 JNF_COCOA_EXIT(env);
1331 }
1332 
1333 /*
1334  * Class:     sun_lwawt_macosx_CAccessible
1335  * Method:    selectionChanged
1336  * Signature: (I)V
1337  */
1338 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CAccessible_selectionChanged
1339 (JNIEnv *env, jclass jklass, jlong element)
1340 {
1341 JNF_COCOA_ENTER(env);
1342     [ThreadUtilities performOnMainThread:@selector(postSelectionChanged) on:(JavaComponentAccessibility *)jlong_to_ptr(element) withObject:nil waitUntilDone:NO];
















































1343 JNF_COCOA_EXIT(env);
1344 }
1345 
1346 /*
1347  * Class:     sun_lwawt_macosx_CAccessible
1348  * Method:    unregisterFromCocoaAXSystem
1349  * Signature: (I)V
1350  */
1351 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CAccessible_unregisterFromCocoaAXSystem
1352 (JNIEnv *env, jclass jklass, jlong element)
1353 {
1354 JNF_COCOA_ENTER(env);
1355     [ThreadUtilities performOnMainThread:@selector(unregisterFromCocoaAXSystem) on:(JavaComponentAccessibility *)jlong_to_ptr(element) withObject:nil waitUntilDone:NO];
1356 JNF_COCOA_EXIT(env);
1357 }
1358 
1359 @implementation TabGroupAccessibility
1360 
1361 - (id)initWithParent:(NSObject *)parent withEnv:(JNIEnv *)env withAccessible:(jobject)accessible withIndex:(jint)index withView:(NSView *)view withJavaRole:(NSString *)javaRole
1362 {




  49 
  50 // these constants are duplicated in CAccessibility.java
  51 #define JAVA_AX_ALL_CHILDREN (-1)
  52 #define JAVA_AX_SELECTED_CHILDREN (-2)
  53 #define JAVA_AX_VISIBLE_CHILDREN (-3)
  54 // If the value is >=0, it's an index
  55 
  56 static JNF_STATIC_MEMBER_CACHE(jm_getChildrenAndRoles, sjc_CAccessibility, "getChildrenAndRoles", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;IZ)[Ljava/lang/Object;");
  57 static JNF_STATIC_MEMBER_CACHE(sjm_getAccessibleComponent, sjc_CAccessibility, "getAccessibleComponent", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljavax/accessibility/AccessibleComponent;");
  58 static JNF_STATIC_MEMBER_CACHE(sjm_getAccessibleValue, sjc_CAccessibility, "getAccessibleValue", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljavax/accessibility/AccessibleValue;");
  59 static JNF_STATIC_MEMBER_CACHE(sjm_getAccessibleName, sjc_CAccessibility, "getAccessibleName", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljava/lang/String;");
  60 static JNF_STATIC_MEMBER_CACHE(sjm_getAccessibleDescription, sjc_CAccessibility, "getAccessibleDescription", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljava/lang/String;");
  61 static JNF_STATIC_MEMBER_CACHE(sjm_isFocusTraversable, sjc_CAccessibility, "isFocusTraversable", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Z");
  62 static JNF_STATIC_MEMBER_CACHE(sjm_getAccessibleIndexInParent, sjc_CAccessibility, "getAccessibleIndexInParent", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)I");
  63 
  64 static JNF_CLASS_CACHE(sjc_CAccessible, "sun/lwawt/macosx/CAccessible");
  65 
  66 static JNF_MEMBER_CACHE(jf_ptr, sjc_CAccessible, "ptr", "J");
  67 static JNF_STATIC_MEMBER_CACHE(sjm_getCAccessible, sjc_CAccessible, "getCAccessible", "(Ljavax/accessibility/Accessible;)Lsun/lwawt/macosx/CAccessible;");
  68 

  69 static jobject sAccessibilityClass = NULL;
  70 
  71 // sAttributeNamesForRoleCache holds the names of the attributes to which each java
  72 // AccessibleRole responds (see AccessibleRole.java).
  73 // This cache is queried before attempting to access a given attribute for a particular role.
  74 static NSMutableDictionary *sAttributeNamesForRoleCache = nil;
  75 static NSObject *sAttributeNamesLOCK = nil;
  76 
  77 @interface TabGroupAccessibility : JavaComponentAccessibility {
  78     NSInteger _numTabs;
  79 }
  80 
  81 - (id)currentTabWithEnv:(JNIEnv *)env withAxContext:(jobject)axContext;
  82 - (NSArray *)tabControlsWithEnv:(JNIEnv *)env withTabGroupAxContext:(jobject)axContext withTabCode:(NSInteger)whichTabs allowIgnored:(BOOL)allowIgnored;
  83 - (NSArray *)contentsWithEnv:(JNIEnv *)env withTabGroupAxContext:(jobject)axContext withTabCode:(NSInteger)whichTabs allowIgnored:(BOOL)allowIgnored;
  84 - (NSArray *)initializeAttributeNamesWithEnv:(JNIEnv *)env;
  85 
  86 - (NSArray *)accessibilityArrayAttributeValues:(NSString *)attribute index:(NSUInteger)index maxCount:(NSUInteger)maxCount;
  87 - (NSArray *)accessibilityChildrenAttribute;
  88 - (id) accessibilityTabsAttribute;


 195 }
 196 
 197 - (void)postValueChanged
 198 {
 199     AWT_ASSERT_APPKIT_THREAD;
 200     NSAccessibilityPostNotification(self, NSAccessibilityValueChangedNotification);
 201 }
 202 
 203 - (void)postSelectedTextChanged
 204 {
 205     AWT_ASSERT_APPKIT_THREAD;
 206     NSAccessibilityPostNotification(self, NSAccessibilitySelectedTextChangedNotification);
 207 }
 208 
 209 - (void)postSelectionChanged
 210 {
 211     AWT_ASSERT_APPKIT_THREAD;
 212     NSAccessibilityPostNotification(self, NSAccessibilitySelectedChildrenChangedNotification);
 213 }
 214 
 215 - (void)postMenuOpened
 216 {
 217     AWT_ASSERT_APPKIT_THREAD;
 218     NSAccessibilityPostNotification(self, (NSString *)kAXMenuOpenedNotification);
 219 }
 220 
 221 - (void)postMenuClosed
 222 {
 223     AWT_ASSERT_APPKIT_THREAD;
 224     NSAccessibilityPostNotification(self, (NSString *)kAXMenuClosedNotification);
 225 }
 226 
 227 - (void)postMenuItemSelected
 228 {
 229     AWT_ASSERT_APPKIT_THREAD;
 230     NSAccessibilityPostNotification(self, (NSString *)kAXMenuItemSelectedNotification);
 231 }
 232 
 233 - (BOOL)isEqual:(id)anObject
 234 {
 235     if (![anObject isKindOfClass:[self class]]) return NO;
 236     JavaComponentAccessibility *accessibility = (JavaComponentAccessibility *)anObject;
 237 
 238     JNIEnv* env = [ThreadUtilities getJNIEnv];
 239     return (*env)->IsSameObject(env, accessibility->fAccessible, fAccessible);
 240 }
 241 
 242 - (BOOL)isAccessibleWithEnv:(JNIEnv *)env forAccessible:(jobject)accessible
 243 {
 244     return (*env)->IsSameObject(env, fAccessible, accessible);
 245 }
 246 
 247 + (void)initialize
 248 {
 249     if (sAttributeNamesForRoleCache == nil) {
 250         sAttributeNamesLOCK = [[NSObject alloc] init];
 251         sAttributeNamesForRoleCache = [[NSMutableDictionary alloc] initWithCapacity:60];
 252     }


 278         NSInteger i;
 279         for (i = 0; i < count; i++) {
 280             jstring jString = JNFNSToJavaString(env, [ignoredKeys objectAtIndex:i]);
 281             (*env)->SetObjectArrayElement(env, result, i, jString);
 282             (*env)->DeleteLocalRef(env, jString);
 283         }
 284 
 285         sAccessibilityClass = JNFCallStaticObjectMethod(env, jm_getAccessibility, result); // AWT_THREADING Safe (known object)
 286     }
 287 }
 288 
 289 + (void)postFocusChanged:(id)message
 290 {
 291     AWT_ASSERT_APPKIT_THREAD;
 292     NSAccessibilityPostNotification([NSApp accessibilityFocusedUIElement], NSAccessibilityFocusedUIElementChangedNotification);
 293 }
 294 
 295 + (jobject) getCAccessible:(jobject)jaccessible withEnv:(JNIEnv *)env {
 296     if (JNFIsInstanceOf(env, jaccessible, &sjc_CAccessible)) {
 297         return jaccessible;
 298     } else if (JNFIsInstanceOf(env, jaccessible, &sjc_Accessible)) {

 299         return JNFCallStaticObjectMethod(env, sjm_getCAccessible, jaccessible);
 300     }
 301     return NULL;
 302 }
 303 
 304 + (NSArray *)childrenOfParent:(JavaComponentAccessibility *)parent withEnv:(JNIEnv *)env withChildrenCode:(NSInteger)whichChildren allowIgnored:(BOOL)allowIgnored
 305 {
 306     if (parent->fAccessible == NULL) return nil;
 307     jobjectArray jchildrenAndRoles = (jobjectArray)JNFCallStaticObjectMethod(env, jm_getChildrenAndRoles, parent->fAccessible, parent->fComponent, whichChildren, allowIgnored); // AWT_THREADING Safe (AWTRunLoop)
 308     if (jchildrenAndRoles == NULL) return nil;
 309 
 310     jsize arrayLen = (*env)->GetArrayLength(env, jchildrenAndRoles);
 311     NSMutableArray *children = [NSMutableArray arrayWithCapacity:arrayLen/2]; //childrenAndRoles array contains two elements (child, role) for each child
 312 
 313     NSInteger i;
 314     NSUInteger childIndex = (whichChildren >= 0) ? whichChildren : 0; // if we're getting one particular child, make sure to set its index correctly
 315     for(i = 0; i < arrayLen; i+=2)
 316     {
 317         jobject /* Accessible */ jchild = (*env)->GetObjectArrayElement(env, jchildrenAndRoles, i);
 318         jobject /* String */ jchildJavaRole = (*env)->GetObjectArrayElement(env, jchildrenAndRoles, i+1);


 367     }
 368 
 369     // otherwise, create a new instance
 370     JavaComponentAccessibility *newChild = nil;
 371     if ([javaRole isEqualToString:@"pagetablist"]) {
 372         newChild = [TabGroupAccessibility alloc];
 373     } else if ([javaRole isEqualToString:@"scrollpane"]) {
 374         newChild = [ScrollAreaAccessibility alloc];
 375     } else {
 376         NSString *nsRole = [sRoles objectForKey:javaRole];
 377         if ([nsRole isEqualToString:NSAccessibilityStaticTextRole] || [nsRole isEqualToString:NSAccessibilityTextAreaRole] || [nsRole isEqualToString:NSAccessibilityTextFieldRole]) {
 378             newChild = [JavaTextAccessibility alloc];
 379         } else {
 380             newChild = [JavaComponentAccessibility alloc];
 381         }
 382     }
 383 
 384     // must init freshly -alloc'd object
 385     [newChild initWithParent:parent withEnv:env withAccessible:jCAX withIndex:index withView:view withJavaRole:javaRole]; // must init new instance
 386 
 387     // If creating a JPopupMenu (not a combobox popup list) need to fire menuOpened.
 388     // This is the only way to know if the menu is opening; visible state change
 389     // can't be caught because the listeners are not set up in time.
 390     if ( [javaRole isEqualToString:@"popupmenu"] &&
 391          ![[parent javaRole] isEqualToString:@"combobox"] ) {
 392         [newChild postMenuOpened];
 393     }
 394 
 395     // must hard retain pointer poked into Java object
 396     [newChild retain];
 397     JNFSetLongField(env, jCAX, jf_ptr, ptr_to_jlong(newChild));
 398     (*env)->DeleteLocalRef(env, jCAX);
 399 
 400     // return autoreleased instance
 401     return [newChild autorelease];
 402 }
 403 
 404 - (NSArray *)initializeAttributeNamesWithEnv:(JNIEnv *)env
 405 {
 406     static JNF_STATIC_MEMBER_CACHE(jm_getInitialAttributeStates, sjc_CAccessibility, "getInitialAttributeStates", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)[Z");
 407 
 408     NSMutableArray *attributeNames = [NSMutableArray arrayWithCapacity:20];
 409     [attributeNames retain];
 410 
 411     // all elements respond to parent, role, role description, window, topLevelUIElement, help
 412     [attributeNames addObject:NSAccessibilityParentAttribute];
 413     [attributeNames addObject:NSAccessibilityRoleAttribute];
 414     [attributeNames addObject:NSAccessibilityRoleDescriptionAttribute];


 641             names = [self initializeAttributeNamesWithEnv:env];
 642 #ifdef JAVA_AX_DEBUG
 643             NSLog(@"Initializing: %s for %@: %@", __FUNCTION__, javaRole, names);
 644 #endif
 645             [sAttributeNamesForRoleCache setObject:names forKey:javaRole];
 646         }
 647         // The above set of attributes is immutable per role, but some objects, if
 648         // they are the child of a list, need to add the selected and index attributes.
 649         id myParent = [self accessibilityParentAttribute];
 650         if ([myParent isKindOfClass:[JavaComponentAccessibility class]]) {
 651             NSString *parentRole = [(JavaComponentAccessibility *)myParent javaRole];
 652             if ([parentRole isEqualToString:@"list"]) {
 653                 NSMutableArray *moreNames =
 654                     [[NSMutableArray alloc] initWithCapacity: [names count] + 2];
 655                 [moreNames addObjectsFromArray: names];
 656                 [moreNames addObject:NSAccessibilitySelectedAttribute];
 657                 [moreNames addObject:NSAccessibilityIndexAttribute];
 658                 return moreNames;
 659             }
 660         }
 661         // popupmenu's return values not selected children
 662         if ( [javaRole isEqualToString:@"popupmenu"] &&
 663              ![[[self parent] javaRole] isEqualToString:@"combobox"] ) {
 664             NSMutableArray *moreNames =
 665                 [[NSMutableArray alloc] initWithCapacity: [names count] + 1];
 666             [moreNames addObjectsFromArray: names];
 667             [moreNames addObject:NSAccessibilityValueAttribute];
 668             return moreNames;
 669         }
 670         return names;
 671 
 672     }  // end @synchronized
 673 
 674 #ifdef JAVA_AX_DEBUG
 675     NSLog(@"Warning in %s: could not find attribute names for role: %@", __FUNCTION__, [self javaRole]);
 676 #endif
 677 
 678     return nil;
 679 }
 680 
 681 // -- accessibility attributes --
 682 
 683 - (BOOL)accessibilityShouldUseUniqueId {
 684     return YES;
 685 }
 686 
 687 - (BOOL)accessibilitySupportsOverriddenAttributes {
 688     return YES;
 689 }


 723 
 724 // specific attributes, in alphabetical order a la
 725 // http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/ObjC_classic/Protocols/NSAccessibility.html
 726 
 727 // Elements that current element contains (NSArray)
 728 - (NSArray *)accessibilityChildrenAttribute
 729 {
 730     JNIEnv* env = [ThreadUtilities getJNIEnv];
 731     NSArray *children = [JavaComponentAccessibility childrenOfParent:self
 732                                                     withEnv:env
 733                                                     withChildrenCode:JAVA_AX_ALL_CHILDREN
 734                                                     allowIgnored:NO];
 735 
 736     NSArray *value = nil;
 737     if ([children count] > 0) {
 738         value = children;
 739     }
 740 
 741     return value;
 742 }
 743 
 744 - (BOOL)accessibilityIsChildrenAttributeSettable
 745 {
 746     return NO;
 747 }
 748 
 749 - (NSUInteger)accessibilityIndexOfChild:(id)child
 750 {
 751     // Only special-casing for Lists, for now. This allows lists to be accessible, fixing radr://3856139 "JLists are broken".
 752     // Will probably want to special-case for Tables when we implement them (radr://3096643 "Accessibility: Table").
 753     // In AppKit, NSMatrixAccessibility (which uses NSAccessibilityListRole), NSTableRowAccessibility, and NSTableViewAccessibility are the
 754     // only ones that override the default implementation in NSAccessibility
 755     if (![[self accessibilityRoleAttribute] isEqualToString:NSAccessibilityListRole]) {
 756         return [super accessibilityIndexOfChild:child];
 757     }
 758 
 759     jint returnValue =
 760         JNFCallStaticIntMethod( [ThreadUtilities getJNIEnv],
 761                                 sjm_getAccessibleIndexInParent,
 762                                 ((JavaComponentAccessibility *)child)->fAccessible,
 763                                 ((JavaComponentAccessibility *)child)->fComponent );


 956     // Now make it into Cocoa screen coords.
 957     point.y = [[[[self view] window] screen] frame].size.height - point.y;
 958 
 959     return [NSValue valueWithPoint:point];
 960 }
 961 
 962 - (BOOL)accessibilityIsPositionAttributeSettable
 963 {
 964     // In AppKit, position is only settable for a window (NSAccessibilityWindowRole). Our windows are taken care of natively, so we don't need to deal with this here
 965     // We *could* make use of Java's AccessibleComponent.setLocation() method. Investigate. radr://3953869
 966     return NO;
 967 }
 968 
 969 // Element type, such as NSAccessibilityRadioButtonRole (NSString). See the role table
 970 // at http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/ObjC_classic/Protocols/NSAccessibility.html
 971 - (NSString *)accessibilityRoleAttribute
 972 {
 973     if (fNSRole == nil) {
 974         NSString *javaRole = [self javaRole];
 975         fNSRole = [sRoles objectForKey:javaRole];
 976         // The sRoles NSMutableDictionary maps popupmenu to Mac's popup button.
 977         // JComboBox behavior currently relies on this.  However this is not the
 978         // proper mapping for a JPopupMenu so fix that.
 979         if ( [javaRole isEqualToString:@"popupmenu"] &&
 980              ![[[self parent] javaRole] isEqualToString:@"combobox"] ) {
 981              fNSRole = NSAccessibilityMenuRole;
 982         }
 983         if (fNSRole == nil) {
 984             // this component has assigned itself a custom AccessibleRole not in the sRoles array
 985             fNSRole = javaRole;
 986         }
 987         [fNSRole retain];
 988     }
 989     return fNSRole;
 990 }
 991 
 992 - (BOOL)accessibilityIsRoleAttributeSettable
 993 {
 994     return NO;
 995 }
 996 
 997 // Localized, user-readable description of role, such as radio button (NSString)
 998 - (NSString *)accessibilityRoleDescriptionAttribute
 999 {
1000     // first ask AppKit for its accessible role description for a given AXRole
1001     NSString *value = NSAccessibilityRoleDescription([self accessibilityRoleAttribute], nil);
1002 
1003     if (value == nil) {
1004         // query java if necessary
1005         static JNF_STATIC_MEMBER_CACHE(jm_getAccessibleRoleDisplayString, sjc_CAccessibility, "getAccessibleRoleDisplayString", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljava/lang/String;");
1006 
1007         JNIEnv* env = [ThreadUtilities getJNIEnv];
1008 
1009         jobject axRole = JNFCallStaticObjectMethod(env, jm_getAccessibleRoleDisplayString, fAccessible, fComponent);
1010         if (axRole != NULL) {
1011             value = JNFJavaToNSString(env, axRole);


1071 - (NSValue *)accessibilitySizeAttribute {
1072     JNIEnv* env = [ThreadUtilities getJNIEnv];
1073     jobject axComponent = JNFCallStaticObjectMethod(env, sjm_getAccessibleComponent, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
1074     NSValue* size = [NSValue valueWithSize:getAxComponentSize(env, axComponent, fComponent)];
1075     (*env)->DeleteLocalRef(env, axComponent);
1076     return size;
1077 }
1078 
1079 - (BOOL)accessibilityIsSizeAttributeSettable
1080 {
1081     // SIZE is settable in windows if [self styleMask] & NSResizableWindowMask - but windows are heavyweight so we're ok here
1082     // SIZE is settable in columns if [[self tableValue] allowsColumnResizing - haven't dealt with columns yet
1083     return NO;
1084 }
1085 
1086 // Element subrole type, such as NSAccessibilityTableRowSubrole (NSString). See the subrole attribute table at
1087 // http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/ObjC_classic/Protocols/NSAccessibility.html
1088 - (NSString *)accessibilitySubroleAttribute
1089 {
1090     NSString *value = nil;
1091     if ([[self javaRole] isEqualToString:@"passwordtext"]) {

1092         value = NSAccessibilitySecureTextFieldSubrole;
1093     }
1094     /*
1095     // other subroles. TableRow and OutlineRow may be relevant to us
1096      NSAccessibilityCloseButtonSubrole // no, heavyweight window takes care of this
1097      NSAccessibilityMinimizeButtonSubrole // "
1098      NSAccessibilityOutlineRowSubrole    // maybe?
1099      NSAccessibilitySecureTextFieldSubrole // currently used
1100      NSAccessibilityTableRowSubrole        // maybe?
1101      NSAccessibilityToolbarButtonSubrole // maybe?
1102      NSAccessibilityUnknownSubrole
1103      NSAccessibilityZoomButtonSubrole    // no, heavyweight window takes care of this
1104      NSAccessibilityStandardWindowSubrole// no, heavyweight window takes care of this
1105      NSAccessibilityDialogSubrole        // maybe?
1106      NSAccessibilitySystemDialogSubrole    // no
1107      NSAccessibilityFloatingWindowSubrole // in 1.5 if we implement these, heavyweight will take care of them anyway
1108      NSAccessibilitySystemFloatingWindowSubrole
1109      NSAccessibilityIncrementArrowSubrole  // no
1110      NSAccessibilityDecrementArrowSubrole  // no
1111      NSAccessibilityIncrementPageSubrole   // no


1147 - (NSWindow *)accessibilityTopLevelUIElementAttribute
1148 {
1149     return [self window];
1150 }
1151 
1152 - (BOOL)accessibilityIsTopLevelUIElementAttributeSettable
1153 {
1154     return NO;
1155 }
1156 
1157 // Element's value (id)
1158 // note that the appKit meaning of "accessibilityValue" is different from the java
1159 // meaning of "accessibleValue", which is specific to numerical values
1160 // (http://java.sun.com/j2se/1.3/docs/api/javax/accessibility/AccessibleValue.html#setCurrentAccessibleValue(java.lang.Number))
1161 - (id)accessibilityValueAttribute
1162 {
1163     static JNF_STATIC_MEMBER_CACHE(jm_getCurrentAccessibleValue, sjc_CAccessibility, "getCurrentAccessibleValue", "(Ljavax/accessibility/AccessibleValue;Ljava/awt/Component;)Ljava/lang/Number;");
1164 
1165     JNIEnv* env = [ThreadUtilities getJNIEnv];
1166 
1167     // Need to handle popupmenus differently.
1168     //
1169     // At least for now don't handle combo box menus.
1170     // This may change when later fixing issues which currently 
1171     // exist for combo boxes, but for now the following is only
1172     // for JPopupMenus, not for combobox menus.
1173     id parent = [self parent];
1174     if ( [[self javaRole] isEqualToString:@"popupmenu"] &&
1175          ![[parent javaRole] isEqualToString:@"combobox"] ) {
1176         NSArray *children =
1177             [JavaComponentAccessibility childrenOfParent:self
1178                                         withEnv:env
1179                                         withChildrenCode:JAVA_AX_ALL_CHILDREN
1180                                         allowIgnored:YES];
1181         if ([children count] > 0) {
1182             // handle case of AXMenuItem
1183             // need to ask menu what is selected
1184             NSArray *selectedChildrenOfMenu =
1185                 [self accessibilitySelectedChildrenAttribute];
1186             JavaComponentAccessibility *selectedMenuItem =
1187                 [selectedChildrenOfMenu objectAtIndex:0];
1188             if (selectedMenuItem != nil) {
1189                 jobject itemValue =
1190                         JNFCallStaticObjectMethod( env,
1191                                                    sjm_getAccessibleName,
1192                                                    selectedMenuItem->fAccessible,
1193                                                    selectedMenuItem->fComponent ); // AWT_THREADING Safe (AWTRunLoop)
1194                 if (itemValue == NULL) {
1195                     return nil;
1196                 }
1197                 NSString* itemString = JNFJavaToNSString(env, itemValue);
1198                 (*env)->DeleteLocalRef(env, itemValue);
1199                 return itemString;
1200             } else {
1201                 return nil;
1202             }
1203         }
1204     }
1205 
1206     // ask Java for the component's accessibleValue. In java, the "accessibleValue" just means a numerical value
1207     // a text value is taken care of in JavaTextAccessibility
1208 
1209     // cmcnote should coalesce these calls into one java call
1210     NSNumber *num = nil;
1211     jobject axValue = JNFCallStaticObjectMethod(env, sjm_getAccessibleValue, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
1212     if (axValue != NULL) {
1213         jobject str = JNFCallStaticObjectMethod(env, jm_getCurrentAccessibleValue, axValue, fComponent);
1214         if (str != NULL) {
1215             num = JNFJavaToNSNumber(env, str); // AWT_THREADING Safe (AWTRunLoop)
1216             (*env)->DeleteLocalRef(env, str);
1217         }
1218         (*env)->DeleteLocalRef(env, axValue);
1219     }
1220     if (num == nil) {
1221         num = [NSNumber numberWithInt:0];
1222     }
1223     return num;
1224 }
1225 


1403 (JNIEnv *env, jclass jklass, jlong element)
1404 {
1405 JNF_COCOA_ENTER(env);
1406     [ThreadUtilities performOnMainThread:@selector(postSelectedTextChanged)
1407                      on:(JavaComponentAccessibility *)jlong_to_ptr(element)
1408                      withObject:nil
1409                      waitUntilDone:NO];
1410 JNF_COCOA_EXIT(env);
1411 }
1412 
1413 /*
1414  * Class:     sun_lwawt_macosx_CAccessible
1415  * Method:    selectionChanged
1416  * Signature: (I)V
1417  */
1418 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CAccessible_selectionChanged
1419 (JNIEnv *env, jclass jklass, jlong element)
1420 {
1421 JNF_COCOA_ENTER(env);
1422     [ThreadUtilities performOnMainThread:@selector(postSelectionChanged) on:(JavaComponentAccessibility *)jlong_to_ptr(element) withObject:nil waitUntilDone:NO];
1423 JNF_COCOA_EXIT(env);
1424 }
1425 
1426 /*
1427  * Class:     sun_lwawt_macosx_CAccessible
1428  * Method:    menuOpened
1429  * Signature: (I)V
1430  */
1431 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CAccessible_menuOpened
1432 (JNIEnv *env, jclass jklass, jlong element)
1433 {
1434 JNF_COCOA_ENTER(env);
1435     [ThreadUtilities performOnMainThread:@selector(postMenuOpened)
1436                      on:(JavaComponentAccessibility *)jlong_to_ptr(element)
1437                      withObject:nil
1438                      waitUntilDone:NO];
1439 JNF_COCOA_EXIT(env);
1440 }
1441 
1442 /*
1443  * Class:     sun_lwawt_macosx_CAccessible
1444  * Method:    menuClosed
1445  * Signature: (I)V
1446  */
1447 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CAccessible_menuClosed
1448 (JNIEnv *env, jclass jklass, jlong element)
1449 {
1450 JNF_COCOA_ENTER(env);
1451     [ThreadUtilities performOnMainThread:@selector(postMenuClosed)
1452                      on:(JavaComponentAccessibility *)jlong_to_ptr(element)
1453                      withObject:nil
1454                      waitUntilDone:NO];
1455 JNF_COCOA_EXIT(env);
1456 }
1457 
1458 /*
1459  * Class:     sun_lwawt_macosx_CAccessible
1460  * Method:    menuItemSelected
1461  * Signature: (I)V
1462  */
1463 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CAccessible_menuItemSelected
1464 (JNIEnv *env, jclass jklass, jlong element)
1465 {
1466 JNF_COCOA_ENTER(env);
1467     [ThreadUtilities performOnMainThread:@selector(postMenuItemSelected)
1468                      on:(JavaComponentAccessibility *)jlong_to_ptr(element)
1469                      withObject:nil
1470                      waitUntilDone:NO];
1471 JNF_COCOA_EXIT(env);
1472 }
1473 
1474 /*
1475  * Class:     sun_lwawt_macosx_CAccessible
1476  * Method:    unregisterFromCocoaAXSystem
1477  * Signature: (I)V
1478  */
1479 JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CAccessible_unregisterFromCocoaAXSystem
1480 (JNIEnv *env, jclass jklass, jlong element)
1481 {
1482 JNF_COCOA_ENTER(env);
1483     [ThreadUtilities performOnMainThread:@selector(unregisterFromCocoaAXSystem) on:(JavaComponentAccessibility *)jlong_to_ptr(element) withObject:nil waitUntilDone:NO];
1484 JNF_COCOA_EXIT(env);
1485 }
1486 
1487 @implementation TabGroupAccessibility
1488 
1489 - (id)initWithParent:(NSObject *)parent withEnv:(JNIEnv *)env withAccessible:(jobject)accessible withIndex:(jint)index withView:(NSView *)view withJavaRole:(NSString *)javaRole
1490 {