jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaComponentAccessibility.m
changeset 37787 de878aeb7ed2
parent 26751 70bac69b37c9
child 38408 3c80511b8982
equal deleted inserted replaced
37786:2752c031a620 37787:de878aeb7ed2
     1 /*
     1 /*
     2  * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    73 // AccessibleRole responds (see AccessibleRole.java).
    73 // AccessibleRole responds (see AccessibleRole.java).
    74 // This cache is queried before attempting to access a given attribute for a particular role.
    74 // This cache is queried before attempting to access a given attribute for a particular role.
    75 static NSMutableDictionary *sAttributeNamesForRoleCache = nil;
    75 static NSMutableDictionary *sAttributeNamesForRoleCache = nil;
    76 static NSObject *sAttributeNamesLOCK = nil;
    76 static NSObject *sAttributeNamesLOCK = nil;
    77 
    77 
    78 
       
    79 @interface TabGroupAccessibility : JavaComponentAccessibility {
    78 @interface TabGroupAccessibility : JavaComponentAccessibility {
    80     NSInteger _numTabs;
    79     NSInteger _numTabs;
    81 }
    80 }
    82 
    81 
    83 - (id)currentTabWithEnv:(JNIEnv *)env withAxContext:(jobject)axContext;
    82 - (id)currentTabWithEnv:(JNIEnv *)env withAxContext:(jobject)axContext;
   135     {
   134     {
   136         fParent = [parent retain];
   135         fParent = [parent retain];
   137         fView = [view retain];
   136         fView = [view retain];
   138         fJavaRole = [javaRole retain];
   137         fJavaRole = [javaRole retain];
   139 
   138 
   140         fAccessible = JNFNewGlobalRef(env, accessible);
   139         fAccessible = (*env)->NewWeakGlobalRef(env, accessible);
   141         fComponent = JNFNewGlobalRef(env, [(AWTView *)fView awtComponent:env]);
   140         
       
   141         jobject jcomponent = [(AWTView *)fView awtComponent:env];
       
   142         fComponent = (*env)->NewWeakGlobalRef(env, jcomponent);
       
   143         (*env)->DeleteLocalRef(env, jcomponent);
   142 
   144 
   143         fIndex = index;
   145         fIndex = index;
   144 
   146 
   145         fActions = nil;
   147         fActions = nil;
   146         fActionsLOCK = [[NSObject alloc] init];
   148         fActionsLOCK = [[NSObject alloc] init];
   164 {
   166 {
   165     [self unregisterFromCocoaAXSystem];
   167     [self unregisterFromCocoaAXSystem];
   166 
   168 
   167     JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
   169     JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
   168 
   170 
   169     JNFDeleteGlobalRef(env, fAccessible);
   171     (*env)->DeleteWeakGlobalRef(env, fAccessible);
   170     fAccessible = NULL;
   172     fAccessible = NULL;
   171 
   173 
   172     JNFDeleteGlobalRef(env, fComponent);
   174     (*env)->DeleteWeakGlobalRef(env, fComponent);
   173     fComponent = NULL;
   175     fComponent = NULL;
   174 
   176 
   175     [fParent release];
   177     [fParent release];
   176     fParent = nil;
   178     fParent = nil;
   177 
   179 
   277     return NULL;
   279     return NULL;
   278 }
   280 }
   279 
   281 
   280 + (NSArray *)childrenOfParent:(JavaComponentAccessibility *)parent withEnv:(JNIEnv *)env withChildrenCode:(NSInteger)whichChildren allowIgnored:(BOOL)allowIgnored
   282 + (NSArray *)childrenOfParent:(JavaComponentAccessibility *)parent withEnv:(JNIEnv *)env withChildrenCode:(NSInteger)whichChildren allowIgnored:(BOOL)allowIgnored
   281 {
   283 {
   282     jobjectArray jchildrenAndRoles = JNFCallStaticObjectMethod(env, jm_getChildrenAndRoles, parent->fAccessible, parent->fComponent, whichChildren, allowIgnored); // AWT_THREADING Safe (AWTRunLoop)
   284     jobjectArray jchildrenAndRoles = (jobjectArray)JNFCallStaticObjectMethod(env, jm_getChildrenAndRoles, parent->fAccessible, parent->fComponent, whichChildren, allowIgnored); // AWT_THREADING Safe (AWTRunLoop)
   283     if (jchildrenAndRoles == NULL) return nil;
   285     if (jchildrenAndRoles == NULL) return nil;
   284 
   286 
   285     jsize arrayLen = (*env)->GetArrayLength(env, jchildrenAndRoles);
   287     jsize arrayLen = (*env)->GetArrayLength(env, jchildrenAndRoles);
   286     NSMutableArray *children = [NSMutableArray arrayWithCapacity:arrayLen/2]; //childrenAndRoles array contains two elements (child, role) for each child
   288     NSMutableArray *children = [NSMutableArray arrayWithCapacity:arrayLen/2]; //childrenAndRoles array contains two elements (child, role) for each child
   287 
   289 
   292         jobject /* Accessible */ jchild = (*env)->GetObjectArrayElement(env, jchildrenAndRoles, i);
   294         jobject /* Accessible */ jchild = (*env)->GetObjectArrayElement(env, jchildrenAndRoles, i);
   293         jobject /* String */ jchildJavaRole = (*env)->GetObjectArrayElement(env, jchildrenAndRoles, i+1);
   295         jobject /* String */ jchildJavaRole = (*env)->GetObjectArrayElement(env, jchildrenAndRoles, i+1);
   294 
   296 
   295         NSString *childJavaRole = nil;
   297         NSString *childJavaRole = nil;
   296         if (jchildJavaRole != NULL) {
   298         if (jchildJavaRole != NULL) {
   297             childJavaRole = JNFJavaToNSString(env, JNFGetObjectField(env, jchildJavaRole, sjf_key));
   299             jobject jkey = JNFGetObjectField(env, jchildJavaRole, sjf_key);
       
   300             childJavaRole = JNFJavaToNSString(env, jkey);
       
   301             (*env)->DeleteLocalRef(env, jkey);
   298         }
   302         }
   299 
   303 
   300         JavaComponentAccessibility *child = [self createWithParent:parent accessible:jchild role:childJavaRole index:childIndex withEnv:env withView:parent->fView];
   304         JavaComponentAccessibility *child = [self createWithParent:parent accessible:jchild role:childJavaRole index:childIndex withEnv:env withView:parent->fView];
       
   305         
       
   306         (*env)->DeleteLocalRef(env, jchild);
       
   307         (*env)->DeleteLocalRef(env, jchildJavaRole);
       
   308         
   301         [children addObject:child];
   309         [children addObject:child];
   302         childIndex++;
   310         childIndex++;
   303     }
   311     }
   304 
   312     (*env)->DeleteLocalRef(env, jchildrenAndRoles);
       
   313     
   305     return children;
   314     return children;
   306 }
   315 }
   307 
   316 
   308 + (JavaComponentAccessibility *)createWithAccessible:(jobject)jaccessible withEnv:(JNIEnv *)env withView:(NSView *)view
   317 + (JavaComponentAccessibility *)createWithAccessible:(jobject)jaccessible withEnv:(JNIEnv *)env withView:(NSView *)view
   309 {
   318 {
   310     jobject jcomponent = [(AWTView *)view awtComponent:env];
   319     jobject jcomponent = [(AWTView *)view awtComponent:env];
   311     jint index = JNFCallStaticIntMethod(env, sjm_getAccessibleIndexInParent, jaccessible, jcomponent);
   320     jint index = JNFCallStaticIntMethod(env, sjm_getAccessibleIndexInParent, jaccessible, jcomponent);
   312     NSString *javaRole = getJavaRole(env, jaccessible, jcomponent);
   321     NSString *javaRole = getJavaRole(env, jaccessible, jcomponent);
   313 
   322     (*env)->DeleteLocalRef(env, jcomponent);
   314     return [self createWithAccessible:jaccessible role:javaRole index:index withEnv:env withView:view];
   323     return [self createWithAccessible:jaccessible role:javaRole index:index withEnv:env withView:view];
   315 }
   324 }
   316 
   325 
   317 + (JavaComponentAccessibility *) createWithAccessible:(jobject)jaccessible role:(NSString *)javaRole index:(jint)index withEnv:(JNIEnv *)env withView:(NSView *)view
   326 + (JavaComponentAccessibility *) createWithAccessible:(jobject)jaccessible role:(NSString *)javaRole index:(jint)index withEnv:(JNIEnv *)env withView:(NSView *)view
   318 {
   327 {
   323 {
   332 {
   324     // try to fetch the jCAX from Java, and return autoreleased
   333     // try to fetch the jCAX from Java, and return autoreleased
   325     jobject jCAX = [JavaComponentAccessibility getCAccessible:jaccessible withEnv:env];
   334     jobject jCAX = [JavaComponentAccessibility getCAccessible:jaccessible withEnv:env];
   326     if (jCAX == NULL) return nil;
   335     if (jCAX == NULL) return nil;
   327     JavaComponentAccessibility *value = (JavaComponentAccessibility *) jlong_to_ptr(JNFGetLongField(env, jCAX, jf_ptr));
   336     JavaComponentAccessibility *value = (JavaComponentAccessibility *) jlong_to_ptr(JNFGetLongField(env, jCAX, jf_ptr));
   328     if (value != nil) return [[value retain] autorelease];
   337     if (value != nil) {
       
   338         (*env)->DeleteLocalRef(env, jCAX);
       
   339         return [[value retain] autorelease];
       
   340     }
   329 
   341 
   330     // otherwise, create a new instance
   342     // otherwise, create a new instance
   331     JavaComponentAccessibility *newChild = nil;
   343     JavaComponentAccessibility *newChild = nil;
   332     if ([javaRole isEqualToString:@"pagetablist"]) {
   344     if ([javaRole isEqualToString:@"pagetablist"]) {
   333         newChild = [TabGroupAccessibility alloc];
   345         newChild = [TabGroupAccessibility alloc];
   346     [newChild initWithParent:parent withEnv:env withAccessible:jCAX withIndex:index withView:view withJavaRole:javaRole]; // must init new instance
   358     [newChild initWithParent:parent withEnv:env withAccessible:jCAX withIndex:index withView:view withJavaRole:javaRole]; // must init new instance
   347 
   359 
   348     // must hard retain pointer poked into Java object
   360     // must hard retain pointer poked into Java object
   349     [newChild retain];
   361     [newChild retain];
   350     JNFSetLongField(env, jCAX, jf_ptr, ptr_to_jlong(newChild));
   362     JNFSetLongField(env, jCAX, jf_ptr, ptr_to_jlong(newChild));
       
   363     (*env)->DeleteLocalRef(env, jCAX);
   351 
   364 
   352     // return autoreleased instance
   365     // return autoreleased instance
   353     return [newChild autorelease];
   366     return [newChild autorelease];
   354 }
   367 }
   355 
   368 
   378         [attributeNames addObject:NSAccessibilitySubroleAttribute];
   391         [attributeNames addObject:NSAccessibilitySubroleAttribute];
   379     }
   392     }
   380 
   393 
   381     // Get all the other accessibility attributes states we need in one swell foop.
   394     // Get all the other accessibility attributes states we need in one swell foop.
   382     // javaRole isn't pulled in because we need protected access to AccessibleRole.key
   395     // javaRole isn't pulled in because we need protected access to AccessibleRole.key
   383     jbooleanArray attributeStates = JNFCallStaticObjectMethod(env, jm_getInitialAttributeStates, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
   396     jbooleanArray attributeStates = (jbooleanArray)JNFCallStaticObjectMethod(env, jm_getInitialAttributeStates, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
   384     if (attributeStates == NULL) return nil;
   397     if (attributeStates == NULL) return nil;
   385     jboolean *attributeStatesArray = (*env)->GetBooleanArrayElements(env, attributeStates, 0);
   398     jboolean *attributeStatesArray = (*env)->GetBooleanArrayElements(env, attributeStates, 0);
   386     if (attributeStatesArray == NULL) {
   399     if (attributeStatesArray == NULL) {
   387         // Note: Java will not be on the stack here so a java exception can't happen and no need to call ExceptionCheck.
   400         // Note: Java will not be on the stack here so a java exception can't happen and no need to call ExceptionCheck.
   388         NSLog(@"%s failed calling GetBooleanArrayElements", __FUNCTION__);
   401         NSLog(@"%s failed calling GetBooleanArrayElements", __FUNCTION__);
   473         //  the first one seems to be the most basic, so this will be used.
   486         //  the first one seems to be the most basic, so this will be used.
   474         // cmcnote: NOT TRUE - Sometimes there are multiple actions, eg sliders have AXDecrement AND AXIncrement (radr://3893192)
   487         // cmcnote: NOT TRUE - Sometimes there are multiple actions, eg sliders have AXDecrement AND AXIncrement (radr://3893192)
   475         JavaAxAction *action = [[JavaAxAction alloc] initWithEnv:env withAccessibleAction:axAction withIndex:0 withComponent:fComponent];
   488         JavaAxAction *action = [[JavaAxAction alloc] initWithEnv:env withAccessibleAction:axAction withIndex:0 withComponent:fComponent];
   476         [fActions setObject:action forKey:[self isMenu] ? NSAccessibilityPickAction : NSAccessibilityPressAction];
   489         [fActions setObject:action forKey:[self isMenu] ? NSAccessibilityPickAction : NSAccessibilityPressAction];
   477         [action release];
   490         [action release];
       
   491         (*env)->DeleteLocalRef(env, axAction);
   478     }
   492     }
   479 }
   493 }
   480 
   494 
   481 - (jobject)axContextWithEnv:(JNIEnv *)env
   495 - (jobject)axContextWithEnv:(JNIEnv *)env
   482 {
   496 {
   483     return getAxContext(env, fAccessible, fComponent);
   497     return getAxContext(env, fAccessible, fComponent);
   484 }
   498 }
   485 
   499 
   486 - (id)parent
   500 - (id)parent
   487 {
   501 {
       
   502     static JNF_CLASS_CACHE(sjc_Window, "java/awt/Window");
   488     static JNF_STATIC_MEMBER_CACHE(sjm_getAccessibleParent, sjc_CAccessibility, "getAccessibleParent", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljavax/accessibility/Accessible;");
   503     static JNF_STATIC_MEMBER_CACHE(sjm_getAccessibleParent, sjc_CAccessibility, "getAccessibleParent", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljavax/accessibility/Accessible;");
       
   504     static JNF_STATIC_MEMBER_CACHE(sjm_getSwingAccessible, sjc_CAccessible, "getSwingAccessible", "(Ljavax/accessibility/Accessible;)Ljavax/accessibility/Accessible;");
   489 
   505 
   490     if(fParent == nil) {
   506     if(fParent == nil) {
   491         JNIEnv* env = [ThreadUtilities getJNIEnv];
   507         JNIEnv* env = [ThreadUtilities getJNIEnv];
   492 
   508 
   493         jobject jparent = JNFCallStaticObjectMethod(env, sjm_getAccessibleParent, fAccessible, fComponent);
   509         jobject jparent = JNFCallStaticObjectMethod(env, sjm_getAccessibleParent, fAccessible, fComponent);
   494 
   510 
   495         if (jparent == NULL) {
   511         if (jparent == NULL) {
   496             fParent = fView;
   512             fParent = fView;
   497         } else {
   513         } else {
   498             fParent = [JavaComponentAccessibility createWithAccessible:jparent withEnv:env withView:fView];
   514             AWTView *view = fView;
       
   515             jobject jax = JNFCallStaticObjectMethod(env, sjm_getSwingAccessible, fAccessible);
       
   516 
       
   517             if (JNFIsInstanceOf(env, jax, &sjc_Window)) {
       
   518                 // In this case jparent is an owner toplevel and we should retrieve its own view
       
   519                 view = [AWTView awtView:env ofAccessible:jparent];
       
   520             }
       
   521             if (view != nil) {
       
   522                 fParent = [JavaComponentAccessibility createWithAccessible:jparent withEnv:env withView:view];
       
   523             }
   499             if (fParent == nil) {
   524             if (fParent == nil) {
   500                 fParent = fView;
   525                 fParent = fView;
   501             }
   526             }
       
   527             (*env)->DeleteLocalRef(env, jparent);
       
   528             (*env)->DeleteLocalRef(env, jax );
   502         }
   529         }
   503         [fParent retain];
   530         [fParent retain];
   504     }
   531     }
   505     return fParent;
   532     return fParent;
   506 }
   533 }
   544 {
   571 {
   545     if (fIndex == -1) {
   572     if (fIndex == -1) {
   546         return NO;
   573         return NO;
   547     }
   574     }
   548 
   575 
   549     return isShowing(env, [self axContextWithEnv:env], fComponent);
   576     jobject axContext = [self axContextWithEnv:env];
       
   577     BOOL showing = isShowing(env, axContext, fComponent);
       
   578     (*env)->DeleteLocalRef(env, axContext);
       
   579     return showing;
   550 }
   580 }
   551 
   581 
   552 // the array of names for each role is cached in the sAttributeNamesForRoleCache
   582 // the array of names for each role is cached in the sAttributeNamesForRoleCache
   553 - (NSArray *)accessibilityAttributeNames
   583 - (NSArray *)accessibilityAttributeNames
   554 {
   584 {
   721 - (NSString *)accessibilityHelpAttribute
   751 - (NSString *)accessibilityHelpAttribute
   722 {
   752 {
   723     JNIEnv* env = [ThreadUtilities getJNIEnv];
   753     JNIEnv* env = [ThreadUtilities getJNIEnv];
   724 
   754 
   725     jobject val = JNFCallStaticObjectMethod(env, sjm_getAccessibleDescription, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
   755     jobject val = JNFCallStaticObjectMethod(env, sjm_getAccessibleDescription, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
   726     return JNFJavaToNSString(env, val);
   756     if (val == NULL) {
       
   757         return @"unknown";
       
   758     }
       
   759     NSString* str = JNFJavaToNSString(env, val);
       
   760     (*env)->DeleteLocalRef(env, val);
       
   761     return str;
   727 }
   762 }
   728 
   763 
   729 - (BOOL)accessibilityIsHelpAttributeSettable
   764 - (BOOL)accessibilityIsHelpAttributeSettable
   730 {
   765 {
   731     return NO;
   766     return NO;
   737     static JNF_STATIC_MEMBER_CACHE(jm_getMaximumAccessibleValue, sjc_CAccessibility, "getMaximumAccessibleValue", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljava/lang/Number;");
   772     static JNF_STATIC_MEMBER_CACHE(jm_getMaximumAccessibleValue, sjc_CAccessibility, "getMaximumAccessibleValue", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljava/lang/Number;");
   738 
   773 
   739     JNIEnv* env = [ThreadUtilities getJNIEnv];
   774     JNIEnv* env = [ThreadUtilities getJNIEnv];
   740 
   775 
   741     jobject axValue = JNFCallStaticObjectMethod(env, jm_getMaximumAccessibleValue, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
   776     jobject axValue = JNFCallStaticObjectMethod(env, jm_getMaximumAccessibleValue, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
   742     return JNFJavaToNSNumber(env, axValue);
   777     if (axValue == NULL) {
       
   778         return [NSNumber numberWithInt:0];
       
   779     }
       
   780     NSNumber* num = JNFJavaToNSNumber(env, axValue);
       
   781     (*env)->DeleteLocalRef(env, axValue);
       
   782     return num;
   743 }
   783 }
   744 
   784 
   745 - (BOOL)accessibilityIsMaxValueAttributeSettable
   785 - (BOOL)accessibilityIsMaxValueAttributeSettable
   746 {
   786 {
   747     return NO;
   787     return NO;
   753     static JNF_STATIC_MEMBER_CACHE(jm_getMinimumAccessibleValue, sjc_CAccessibility, "getMinimumAccessibleValue", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljava/lang/Number;");
   793     static JNF_STATIC_MEMBER_CACHE(jm_getMinimumAccessibleValue, sjc_CAccessibility, "getMinimumAccessibleValue", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljava/lang/Number;");
   754 
   794 
   755     JNIEnv* env = [ThreadUtilities getJNIEnv];
   795     JNIEnv* env = [ThreadUtilities getJNIEnv];
   756 
   796 
   757     jobject axValue = JNFCallStaticObjectMethod(env, jm_getMinimumAccessibleValue, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
   797     jobject axValue = JNFCallStaticObjectMethod(env, jm_getMinimumAccessibleValue, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
   758     return JNFJavaToNSNumber(env, axValue);
   798     if (axValue == NULL) {
       
   799         return [NSNumber numberWithInt:0];
       
   800     }
       
   801     NSNumber* num = JNFJavaToNSNumber(env, axValue);
       
   802     (*env)->DeleteLocalRef(env, axValue);
       
   803     return num;
   759 }
   804 }
   760 
   805 
   761 - (BOOL)accessibilityIsMinValueAttributeSettable
   806 - (BOOL)accessibilityIsMinValueAttributeSettable
   762 {
   807 {
   763     return NO;
   808     return NO;
   768     JNIEnv* env = [ThreadUtilities getJNIEnv];
   813     JNIEnv* env = [ThreadUtilities getJNIEnv];
   769     jobject axContext = [self axContextWithEnv:env];
   814     jobject axContext = [self axContextWithEnv:env];
   770 
   815 
   771     // cmcnote - should batch these two calls into one that returns an array of two bools, one for vertical and one for horiz
   816     // cmcnote - should batch these two calls into one that returns an array of two bools, one for vertical and one for horiz
   772     if (isVertical(env, axContext, fComponent)) {
   817     if (isVertical(env, axContext, fComponent)) {
       
   818         (*env)->DeleteLocalRef(env, axContext);
   773         return NSAccessibilityVerticalOrientationValue;
   819         return NSAccessibilityVerticalOrientationValue;
   774     }
   820     }
   775 
   821 
   776     if (isHorizontal(env, axContext, fComponent)) {
   822     if (isHorizontal(env, axContext, fComponent)) {
       
   823         (*env)->DeleteLocalRef(env, axContext);
   777         return NSAccessibilityHorizontalOrientationValue;
   824         return NSAccessibilityHorizontalOrientationValue;
   778     }
   825     }
   779 
   826 
       
   827     (*env)->DeleteLocalRef(env, axContext);
   780     return nil;
   828     return nil;
   781 }
   829 }
   782 
   830 
   783 - (BOOL)accessibilityIsOrientationAttributeSettable
   831 - (BOOL)accessibilityIsOrientationAttributeSettable
   784 {
   832 {
   806     // bottom left based screen coords
   854     // bottom left based screen coords
   807 
   855 
   808     // Get the java screen coords, and make a NSPoint of the bottom left of the AxComponent.
   856     // Get the java screen coords, and make a NSPoint of the bottom left of the AxComponent.
   809     NSSize size = getAxComponentSize(env, axComponent, fComponent);
   857     NSSize size = getAxComponentSize(env, axComponent, fComponent);
   810     NSPoint point = getAxComponentLocationOnScreen(env, axComponent, fComponent);
   858     NSPoint point = getAxComponentLocationOnScreen(env, axComponent, fComponent);
       
   859     (*env)->DeleteLocalRef(env, axComponent);
   811 
   860 
   812     point.y += size.height;
   861     point.y += size.height;
   813 
   862 
   814     // Now make it into Cocoa screen coords.
   863     // Now make it into Cocoa screen coords.
   815     point.y = [[[[self view] window] screen] frame].size.height - point.y;
   864     point.y = [[[[self view] window] screen] frame].size.height - point.y;
   855         static JNF_STATIC_MEMBER_CACHE(jm_getAccessibleRoleDisplayString, sjc_CAccessibility, "getAccessibleRoleDisplayString", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljava/lang/String;");
   904         static JNF_STATIC_MEMBER_CACHE(jm_getAccessibleRoleDisplayString, sjc_CAccessibility, "getAccessibleRoleDisplayString", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljava/lang/String;");
   856 
   905 
   857         JNIEnv* env = [ThreadUtilities getJNIEnv];
   906         JNIEnv* env = [ThreadUtilities getJNIEnv];
   858 
   907 
   859         jobject axRole = JNFCallStaticObjectMethod(env, jm_getAccessibleRoleDisplayString, fAccessible, fComponent);
   908         jobject axRole = JNFCallStaticObjectMethod(env, jm_getAccessibleRoleDisplayString, fAccessible, fComponent);
   860         if(axRole != NULL) {
   909         if (axRole != NULL) {
   861             value = JNFJavaToNSString(env, axRole);
   910             value = JNFJavaToNSString(env, axRole);
       
   911             (*env)->DeleteLocalRef(env, axRole);
   862         } else {
   912         } else {
   863             value = @"unknown";
   913             value = @"unknown";
   864         }
   914         }
   865     }
   915     }
   866 
   916 
   891 
   941 
   892 // Element size (NSValue)
   942 // Element size (NSValue)
   893 - (NSValue *)accessibilitySizeAttribute {
   943 - (NSValue *)accessibilitySizeAttribute {
   894     JNIEnv* env = [ThreadUtilities getJNIEnv];
   944     JNIEnv* env = [ThreadUtilities getJNIEnv];
   895     jobject axComponent = JNFCallStaticObjectMethod(env, sjm_getAccessibleComponent, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
   945     jobject axComponent = JNFCallStaticObjectMethod(env, sjm_getAccessibleComponent, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
   896     return [NSValue valueWithSize:getAxComponentSize(env, axComponent, fComponent)];
   946     NSValue* size = [NSValue valueWithSize:getAxComponentSize(env, axComponent, fComponent)];
       
   947     (*env)->DeleteLocalRef(env, axComponent);
       
   948     return size;
   897 }
   949 }
   898 
   950 
   899 - (BOOL)accessibilityIsSizeAttributeSettable
   951 - (BOOL)accessibilityIsSizeAttributeSettable
   900 {
   952 {
   901     // SIZE is settable in windows if [self styleMask] & NSResizableWindowMask - but windows are heavyweight so we're ok here
   953     // SIZE is settable in windows if [self styleMask] & NSResizableWindowMask - but windows are heavyweight so we're ok here
   950     }
  1002     }
   951 
  1003 
   952     JNIEnv* env = [ThreadUtilities getJNIEnv];
  1004     JNIEnv* env = [ThreadUtilities getJNIEnv];
   953 
  1005 
   954     jobject val = JNFCallStaticObjectMethod(env, sjm_getAccessibleName, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
  1006     jobject val = JNFCallStaticObjectMethod(env, sjm_getAccessibleName, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
   955     return JNFJavaToNSString(env, val);
  1007     if (val == NULL) {
       
  1008         return @"unknown";
       
  1009     }
       
  1010     NSString* str = JNFJavaToNSString(env, val);
       
  1011     (*env)->DeleteLocalRef(env, val);
       
  1012     return str;
   956 }
  1013 }
   957 
  1014 
   958 - (BOOL)accessibilityIsTitleAttributeSettable
  1015 - (BOOL)accessibilityIsTitleAttributeSettable
   959 {
  1016 {
   960     return NO;
  1017     return NO;
   982 
  1039 
   983     // ask Java for the component's accessibleValue. In java, the "accessibleValue" just means a numerical value
  1040     // ask Java for the component's accessibleValue. In java, the "accessibleValue" just means a numerical value
   984     // a text value is taken care of in JavaTextAccessibility
  1041     // a text value is taken care of in JavaTextAccessibility
   985 
  1042 
   986     // cmcnote should coalesce these calls into one java call
  1043     // cmcnote should coalesce these calls into one java call
       
  1044     NSNumber *num = nil;
   987     jobject axValue = JNFCallStaticObjectMethod(env, sjm_getAccessibleValue, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
  1045     jobject axValue = JNFCallStaticObjectMethod(env, sjm_getAccessibleValue, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)
   988     return JNFJavaToNSNumber(env, JNFCallStaticObjectMethod(env, jm_getCurrentAccessibleValue, axValue, fComponent)); // AWT_THREADING Safe (AWTRunLoop)
  1046     if (axValue != NULL) {
       
  1047         jobject str = JNFCallStaticObjectMethod(env, jm_getCurrentAccessibleValue, axValue, fComponent);
       
  1048         if (str != NULL) {
       
  1049             num = JNFJavaToNSNumber(env, str); // AWT_THREADING Safe (AWTRunLoop)
       
  1050             (*env)->DeleteLocalRef(env, str);
       
  1051         }
       
  1052         (*env)->DeleteLocalRef(env, axValue);
       
  1053     }
       
  1054     if (num == nil) {
       
  1055         num = [NSNumber numberWithInt:0];
       
  1056     }
       
  1057     return num;
   989 }
  1058 }
   990 
  1059 
   991 - (BOOL)accessibilityIsValueAttributeSettable
  1060 - (BOOL)accessibilityIsValueAttributeSettable
   992 {
  1061 {
   993     // according ot AppKit sources, in general the value attribute is not settable, except in the cases
  1062     // according ot AppKit sources, in general the value attribute is not settable, except in the cases
  1082     jobject jparent = fComponent;
  1151     jobject jparent = fComponent;
  1083 
  1152 
  1084     id value = nil;
  1153     id value = nil;
  1085     if (JNFIsInstanceOf(env, jparent, &jc_Container)) {
  1154     if (JNFIsInstanceOf(env, jparent, &jc_Container)) {
  1086         jobject jaccessible = JNFCallStaticObjectMethod(env, jm_accessibilityHitTest, jparent, (jfloat)point.x, (jfloat)point.y); // AWT_THREADING Safe (AWTRunLoop)
  1155         jobject jaccessible = JNFCallStaticObjectMethod(env, jm_accessibilityHitTest, jparent, (jfloat)point.x, (jfloat)point.y); // AWT_THREADING Safe (AWTRunLoop)
  1087         value = [JavaComponentAccessibility createWithAccessible:jaccessible withEnv:env withView:fView];
  1156         if (jaccessible != NULL) {
       
  1157             value = [JavaComponentAccessibility createWithAccessible:jaccessible withEnv:env withView:fView];
       
  1158             (*env)->DeleteLocalRef(env, jaccessible);
       
  1159         }
  1088     }
  1160     }
  1089 
  1161 
  1090     if (value == nil) {
  1162     if (value == nil) {
  1091         value = self;
  1163         value = self;
  1092     }
  1164     }
  1114     
  1186     
  1115     if (focused != NULL) {
  1187     if (focused != NULL) {
  1116         if (JNFIsInstanceOf(env, focused, &sjc_Accessible)) {
  1188         if (JNFIsInstanceOf(env, focused, &sjc_Accessible)) {
  1117             value = [JavaComponentAccessibility createWithAccessible:focused withEnv:env withView:fView];
  1189             value = [JavaComponentAccessibility createWithAccessible:focused withEnv:env withView:fView];
  1118         }
  1190         }
       
  1191         (*env)->DeleteLocalRef(env, focused);
  1119     }
  1192     }
  1120 
  1193 
  1121     if (value == nil) {
  1194     if (value == nil) {
  1122         value = self;
  1195         value = self;
  1123     }
  1196     }
  1220     JavaComponentAccessibility *aTab;
  1293     JavaComponentAccessibility *aTab;
  1221     NSInteger i;
  1294     NSInteger i;
  1222     for (i = 0; i < _numTabs; i++) {
  1295     for (i = 0; i < _numTabs; i++) {
  1223         aTab = (JavaComponentAccessibility *)[tabs objectAtIndex:i];
  1296         aTab = (JavaComponentAccessibility *)[tabs objectAtIndex:i];
  1224         if ([aTab isAccessibleWithEnv:env forAccessible:selAccessible]) {
  1297         if ([aTab isAccessibleWithEnv:env forAccessible:selAccessible]) {
       
  1298             (*env)->DeleteLocalRef(env, selAccessible);
  1225             return aTab;
  1299             return aTab;
  1226         }
  1300         }
  1227     }
  1301     }
  1228 
  1302     (*env)->DeleteLocalRef(env, selAccessible);
  1229     return nil;
  1303     return nil;
  1230 }
  1304 }
  1231 
  1305 
  1232 - (NSArray *)tabControlsWithEnv:(JNIEnv *)env withTabGroupAxContext:(jobject)axContext withTabCode:(NSInteger)whichTabs allowIgnored:(BOOL)allowIgnored
  1306 - (NSArray *)tabControlsWithEnv:(JNIEnv *)env withTabGroupAxContext:(jobject)axContext withTabCode:(NSInteger)whichTabs allowIgnored:(BOOL)allowIgnored
  1233 {
  1307 {
  1234     jobjectArray jtabsAndRoles = JNFCallStaticObjectMethod(env, jm_getChildrenAndRoles, fAccessible, fComponent, whichTabs, allowIgnored); // AWT_THREADING Safe (AWTRunLoop)
  1308     jobjectArray jtabsAndRoles = (jobjectArray)JNFCallStaticObjectMethod(env, jm_getChildrenAndRoles, fAccessible, fComponent, whichTabs, allowIgnored); // AWT_THREADING Safe (AWTRunLoop)
  1235     if(jtabsAndRoles == NULL) return nil;
  1309     if(jtabsAndRoles == NULL) return nil;
  1236 
  1310 
  1237     jsize arrayLen = (*env)->GetArrayLength(env, jtabsAndRoles);
  1311     jsize arrayLen = (*env)->GetArrayLength(env, jtabsAndRoles);
  1238     if (arrayLen == 0) return nil;
  1312     if (arrayLen == 0) {
  1239 
  1313         (*env)->DeleteLocalRef(env, jtabsAndRoles);
       
  1314         return nil;
       
  1315     }
  1240     NSMutableArray *tabs = [NSMutableArray arrayWithCapacity:(arrayLen/2)];
  1316     NSMutableArray *tabs = [NSMutableArray arrayWithCapacity:(arrayLen/2)];
  1241 
  1317 
  1242     // all of the tabs have the same role, so we can just find out what that is here and use it for all the tabs
  1318     // all of the tabs have the same role, so we can just find out what that is here and use it for all the tabs
  1243     jobject jtabJavaRole = (*env)->GetObjectArrayElement(env, jtabsAndRoles, 1); // the array entries alternate between tab/role, starting with tab. so the first role is entry 1.
  1319     jobject jtabJavaRole = (*env)->GetObjectArrayElement(env, jtabsAndRoles, 1); // the array entries alternate between tab/role, starting with tab. so the first role is entry 1.
  1244     if (jtabJavaRole == NULL) return nil;
  1320     if (jtabJavaRole == NULL) {
  1245 
  1321         (*env)->DeleteLocalRef(env, jtabsAndRoles);
  1246     NSString *tabJavaRole = JNFJavaToNSString(env, JNFGetObjectField(env, jtabJavaRole, sjf_key));
  1322         return nil;
       
  1323     }
       
  1324     jobject jkey = JNFGetObjectField(env, jtabJavaRole, sjf_key);
       
  1325     NSString *tabJavaRole = JNFJavaToNSString(env, jkey);
       
  1326     (*env)->DeleteLocalRef(env, jkey);
  1247 
  1327 
  1248     NSInteger i;
  1328     NSInteger i;
  1249     NSUInteger tabIndex = (whichTabs >= 0) ? whichTabs : 0; // if we're getting one particular child, make sure to set its index correctly
  1329     NSUInteger tabIndex = (whichTabs >= 0) ? whichTabs : 0; // if we're getting one particular child, make sure to set its index correctly
  1250     for(i = 0; i < arrayLen; i+=2) {
  1330     for(i = 0; i < arrayLen; i+=2) {
  1251         jobject jtab = (*env)->GetObjectArrayElement(env, jtabsAndRoles, i);
  1331         jobject jtab = (*env)->GetObjectArrayElement(env, jtabsAndRoles, i);
  1252         JavaComponentAccessibility *tab = [[[TabGroupControlAccessibility alloc] initWithParent:self withEnv:env withAccessible:jtab withIndex:tabIndex withTabGroup:axContext withView:[self view] withJavaRole:tabJavaRole] autorelease];
  1332         JavaComponentAccessibility *tab = [[[TabGroupControlAccessibility alloc] initWithParent:self withEnv:env withAccessible:jtab withIndex:tabIndex withTabGroup:axContext withView:[self view] withJavaRole:tabJavaRole] autorelease];
       
  1333         (*env)->DeleteLocalRef(env, jtab);
  1253         [tabs addObject:tab];
  1334         [tabs addObject:tab];
  1254         tabIndex++;
  1335         tabIndex++;
  1255     }
  1336     }
  1256 
  1337     (*env)->DeleteLocalRef(env, jtabsAndRoles);
  1257     return tabs;
  1338     return tabs;
  1258 }
  1339 }
  1259 
  1340 
  1260 - (NSArray *)contentsWithEnv:(JNIEnv *)env withTabGroupAxContext:(jobject)axContext withTabCode:(NSInteger)whichTabs allowIgnored:(BOOL)allowIgnored
  1341 - (NSArray *)contentsWithEnv:(JNIEnv *)env withTabGroupAxContext:(jobject)axContext withTabCode:(NSInteger)whichTabs allowIgnored:(BOOL)allowIgnored
  1261 {
  1342 {
  1270 
  1351 
  1271 - (id) accessibilityTabsAttribute
  1352 - (id) accessibilityTabsAttribute
  1272 {
  1353 {
  1273     JNIEnv *env = [ThreadUtilities getJNIEnv];
  1354     JNIEnv *env = [ThreadUtilities getJNIEnv];
  1274     jobject axContext = [self axContextWithEnv:env];
  1355     jobject axContext = [self axContextWithEnv:env];
  1275     return [self tabControlsWithEnv:env withTabGroupAxContext:axContext withTabCode:JAVA_AX_ALL_CHILDREN allowIgnored:NO];
  1356     id tabs = [self tabControlsWithEnv:env withTabGroupAxContext:axContext withTabCode:JAVA_AX_ALL_CHILDREN allowIgnored:NO];
       
  1357     (*env)->DeleteLocalRef(env, axContext);
       
  1358     return tabs;
  1276 }
  1359 }
  1277 
  1360 
  1278 - (BOOL)accessibilityIsTabsAttributeSettable
  1361 - (BOOL)accessibilityIsTabsAttributeSettable
  1279 {
  1362 {
  1280     return NO; //cmcnote: not sure.
  1363     return NO; //cmcnote: not sure.
  1290 
  1373 
  1291 - (NSArray *) accessibilityContentsAttribute
  1374 - (NSArray *) accessibilityContentsAttribute
  1292 {
  1375 {
  1293     JNIEnv *env = [ThreadUtilities getJNIEnv];
  1376     JNIEnv *env = [ThreadUtilities getJNIEnv];
  1294     jobject axContext = [self axContextWithEnv:env];
  1377     jobject axContext = [self axContextWithEnv:env];
  1295     return [self contentsWithEnv:env withTabGroupAxContext:axContext withTabCode:JAVA_AX_ALL_CHILDREN allowIgnored:NO];
  1378     NSArray* cont = [self contentsWithEnv:env withTabGroupAxContext:axContext withTabCode:JAVA_AX_ALL_CHILDREN allowIgnored:NO];
       
  1379     (*env)->DeleteLocalRef(env, axContext);
       
  1380     return cont;
  1296 }
  1381 }
  1297 
  1382 
  1298 - (BOOL)accessibilityIsContentsAttributeSettable
  1383 - (BOOL)accessibilityIsContentsAttributeSettable
  1299 {
  1384 {
  1300     return NO;
  1385     return NO;
  1303 // axValue is the currently selected tab
  1388 // axValue is the currently selected tab
  1304 -(id) accessibilityValueAttribute
  1389 -(id) accessibilityValueAttribute
  1305 {
  1390 {
  1306     JNIEnv *env = [ThreadUtilities getJNIEnv];
  1391     JNIEnv *env = [ThreadUtilities getJNIEnv];
  1307     jobject axContext = [self axContextWithEnv:env];
  1392     jobject axContext = [self axContextWithEnv:env];
  1308     return [self currentTabWithEnv:env withAxContext:axContext];
  1393     id val = [self currentTabWithEnv:env withAxContext:axContext];
       
  1394     (*env)->DeleteLocalRef(env, axContext);
       
  1395     return val;
  1309 }
  1396 }
  1310 
  1397 
  1311 - (BOOL)accessibilityIsValueAttributeSettable
  1398 - (BOOL)accessibilityIsValueAttributeSettable
  1312 {
  1399 {
  1313     return YES;
  1400     return YES;
  1320     if (![number boolValue]) return;
  1407     if (![number boolValue]) return;
  1321 
  1408 
  1322     JNIEnv *env = [ThreadUtilities getJNIEnv];
  1409     JNIEnv *env = [ThreadUtilities getJNIEnv];
  1323     jobject axContext = [self axContextWithEnv:env];
  1410     jobject axContext = [self axContextWithEnv:env];
  1324     setAxContextSelection(env, axContext, fIndex, fComponent);
  1411     setAxContextSelection(env, axContext, fIndex, fComponent);
       
  1412     (*env)->DeleteLocalRef(env, axContext);
  1325 }
  1413 }
  1326 
  1414 
  1327 - (NSArray *)accessibilityChildrenAttribute
  1415 - (NSArray *)accessibilityChildrenAttribute
  1328 {
  1416 {
  1329     //children = AXTabs + AXContents
  1417     //children = AXTabs + AXContents
  1355             children= [self contentsWithEnv:env withTabGroupAxContext:axContext withTabCode:(index-[self numTabs]) allowIgnored:NO];
  1443             children= [self contentsWithEnv:env withTabGroupAxContext:axContext withTabCode:(index-[self numTabs]) allowIgnored:NO];
  1356             if ([children count] > 0) {
  1444             if ([children count] > 0) {
  1357                 result = children;
  1445                 result = children;
  1358             }
  1446             }
  1359         }
  1447         }
       
  1448         (*env)->DeleteLocalRef(env, axContext);
  1360     } else {
  1449     } else {
  1361         result = [super accessibilityArrayAttributeValues:attribute index:index maxCount:maxCount];
  1450         result = [super accessibilityArrayAttributeValues:attribute index:index maxCount:maxCount];
  1362     }
  1451     }
  1363     return result;
  1452     return result;
  1364 }
  1453 }
  1373 - (id)initWithParent:(NSObject *)parent withEnv:(JNIEnv *)env withAccessible:(jobject)accessible withIndex:(jint)index withTabGroup:(jobject)tabGroup withView:(NSView *)view withJavaRole:(NSString *)javaRole
  1462 - (id)initWithParent:(NSObject *)parent withEnv:(JNIEnv *)env withAccessible:(jobject)accessible withIndex:(jint)index withTabGroup:(jobject)tabGroup withView:(NSView *)view withJavaRole:(NSString *)javaRole
  1374 {
  1463 {
  1375     self = [super initWithParent:parent withEnv:env withAccessible:accessible withIndex:index withView:view withJavaRole:javaRole];
  1464     self = [super initWithParent:parent withEnv:env withAccessible:accessible withIndex:index withView:view withJavaRole:javaRole];
  1376     if (self) {
  1465     if (self) {
  1377         if (tabGroup != NULL) {
  1466         if (tabGroup != NULL) {
  1378             fTabGroupAxContext = JNFNewGlobalRef(env, tabGroup);
  1467             fTabGroupAxContext = JNFNewWeakGlobalRef(env, tabGroup);
  1379         } else {
  1468         } else {
  1380             fTabGroupAxContext = NULL;
  1469             fTabGroupAxContext = NULL;
  1381         }
  1470         }
  1382     }
  1471     }
  1383     return self;
  1472     return self;
  1386 - (void)dealloc
  1475 - (void)dealloc
  1387 {
  1476 {
  1388     JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
  1477     JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
  1389 
  1478 
  1390     if (fTabGroupAxContext != NULL) {
  1479     if (fTabGroupAxContext != NULL) {
  1391         JNFDeleteGlobalRef(env, fTabGroupAxContext);
  1480         JNFDeleteWeakGlobalRef(env, fTabGroupAxContext);
  1392         fTabGroupAxContext = NULL;
  1481         fTabGroupAxContext = NULL;
  1393     }
  1482     }
  1394 
  1483 
  1395     [super dealloc];
  1484     [super dealloc];
  1396 }
  1485 }
  1397 
  1486 
  1398 - (id)accessibilityValueAttribute
  1487 - (id)accessibilityValueAttribute
  1399 {
  1488 {
  1400     JNIEnv *env = [ThreadUtilities getJNIEnv];
  1489     JNIEnv *env = [ThreadUtilities getJNIEnv];
  1401     jobject axContext = [self axContextWithEnv:env];
  1490     jobject axContext = [self axContextWithEnv:env];
       
  1491     jobject selAccessible = getAxContextSelection(env, [self tabGroup], fIndex, fComponent);
  1402 
  1492 
  1403     // Returns the current selection of the page tab list
  1493     // Returns the current selection of the page tab list
  1404     return [NSNumber numberWithBool:ObjectEquals(env, axContext, getAxContextSelection(env, [self tabGroup], fIndex, fComponent), fComponent)];
  1494     id val = [NSNumber numberWithBool:ObjectEquals(env, axContext, selAccessible, fComponent)];
       
  1495 
       
  1496     (*env)->DeleteLocalRef(env, selAccessible);
       
  1497     (*env)->DeleteLocalRef(env, axContext);
       
  1498     return val;
  1405 }
  1499 }
  1406 
  1500 
  1407 - (void)getActionsWithEnv:(JNIEnv *)env
  1501 - (void)getActionsWithEnv:(JNIEnv *)env
  1408 {
  1502 {
  1409     TabGroupAction *action = [[TabGroupAction alloc] initWithEnv:env withTabGroup:[self tabGroup] withIndex:fIndex withComponent:fComponent];
  1503     TabGroupAction *action = [[TabGroupAction alloc] initWithEnv:env withTabGroup:[self tabGroup] withIndex:fIndex withComponent:fComponent];
  1414 - (jobject)tabGroup
  1508 - (jobject)tabGroup
  1415 {
  1509 {
  1416     if (fTabGroupAxContext == NULL) {
  1510     if (fTabGroupAxContext == NULL) {
  1417         JNIEnv* env = [ThreadUtilities getJNIEnv];
  1511         JNIEnv* env = [ThreadUtilities getJNIEnv];
  1418         jobject tabGroupAxContext = [(JavaComponentAccessibility *)[self parent] axContextWithEnv:env];
  1512         jobject tabGroupAxContext = [(JavaComponentAccessibility *)[self parent] axContextWithEnv:env];
  1419         fTabGroupAxContext = JNFNewGlobalRef(env, tabGroupAxContext);
  1513         fTabGroupAxContext = JNFNewWeakGlobalRef(env, tabGroupAxContext);
       
  1514         (*env)->DeleteLocalRef(env, tabGroupAxContext);
  1420     }
  1515     }
  1421     return fTabGroupAxContext;
  1516     return fTabGroupAxContext;
  1422 }
  1517 }
  1423 
  1518 
  1424 @end
  1519 @end
  1449     NSEnumerator *enumerator = [children objectEnumerator];
  1544     NSEnumerator *enumerator = [children objectEnumerator];
  1450     while ((aElement = (JavaComponentAccessibility *)[enumerator nextObject])) {
  1545     while ((aElement = (JavaComponentAccessibility *)[enumerator nextObject])) {
  1451         if ([[aElement accessibilityRoleAttribute] isEqualToString:NSAccessibilityScrollBarRole]) {
  1546         if ([[aElement accessibilityRoleAttribute] isEqualToString:NSAccessibilityScrollBarRole]) {
  1452             jobject elementAxContext = [aElement axContextWithEnv:env];
  1547             jobject elementAxContext = [aElement axContextWithEnv:env];
  1453             if (isHorizontal(env, elementAxContext, fComponent)) {
  1548             if (isHorizontal(env, elementAxContext, fComponent)) {
       
  1549                 (*env)->DeleteLocalRef(env, elementAxContext);
  1454                 return aElement;
  1550                 return aElement;
  1455             }
  1551             }
       
  1552             (*env)->DeleteLocalRef(env, elementAxContext);
  1456         }
  1553         }
  1457     }
  1554     }
  1458 
  1555 
  1459     return nil;
  1556     return nil;
  1460 }
  1557 }
  1476     JavaComponentAccessibility *aElement;
  1573     JavaComponentAccessibility *aElement;
  1477     while ((aElement = (JavaComponentAccessibility *)[enumerator nextObject])) {
  1574     while ((aElement = (JavaComponentAccessibility *)[enumerator nextObject])) {
  1478         if ([[aElement accessibilityRoleAttribute] isEqualToString:NSAccessibilityScrollBarRole]) {
  1575         if ([[aElement accessibilityRoleAttribute] isEqualToString:NSAccessibilityScrollBarRole]) {
  1479             jobject elementAxContext = [aElement axContextWithEnv:env];
  1576             jobject elementAxContext = [aElement axContextWithEnv:env];
  1480             if (isVertical(env, elementAxContext, fComponent)) {
  1577             if (isVertical(env, elementAxContext, fComponent)) {
       
  1578                 (*env)->DeleteLocalRef(env, elementAxContext);
  1481                 return aElement;
  1579                 return aElement;
  1482             }
  1580             }
       
  1581             (*env)->DeleteLocalRef(env, elementAxContext);
  1483         }
  1582         }
  1484     }
  1583     }
  1485 
  1584 
  1486     return nil;
  1585     return nil;
  1487 }
  1586 }