1 /*
   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.
   4  *
   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
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #import "JavaAccessibilityUtilities.h"
  27 #import "JNIUtilities.h"
  28 
  29 #import <AppKit/AppKit.h>
  30 
  31 static BOOL JavaAccessibilityIsSupportedAttribute(id element, NSString *attribute);
  32 static void JavaAccessibilityLogError(NSString *message);
  33 static void _JavaAccessibilityRaiseException(NSString *reason, SInt32 errorCode);
  34 static NSString *AttributeWithoutAXPrefix(NSString *attribute);
  35 static SEL JavaAccessibilityAttributeGetter(NSString *attribute);
  36 static SEL JavaAccessibilityAttributeSettableTester(NSString *attribute);
  37 static SEL JavaAccessibilityAttributeSetter(NSString *attribute);
  38 
  39 NSString *const JavaAccessibilityIgnore = @"JavaAxIgnore";
  40 
  41 NSMutableDictionary *sRoles = nil;
  42 void initializeRoles();
  43 
  44 // Unique
  45 static jclass sjc_AccessibleState = NULL;
  46 #define GET_ACCESSIBLESTATE_CLASS_RETURN(ret) \
  47      GET_CLASS_RETURN(sjc_AccessibleState, "javax/accessibility/AccessibleState", ret);
  48 
  49 static jclass sjc_CAccessibility = NULL;
  50 
  51 NSSize getAxComponentSize(JNIEnv *env, jobject axComponent, jobject component)
  52 {
  53     DECLARE_CLASS_RETURN(jc_Dimension, "java/awt/Dimension", NSZeroSize);
  54     DECLARE_FIELD_RETURN(jf_width, jc_Dimension, "width", "I", NSZeroSize);
  55     DECLARE_FIELD_RETURN(jf_height, jc_Dimension, "height", "I", NSZeroSize);
  56     DECLARE_STATIC_METHOD_RETURN(jm_getSize, sjc_CAccessibility, "getSize",
  57            "(Ljavax/accessibility/AccessibleComponent;Ljava/awt/Component;)Ljava/awt/Dimension;", NSZeroSize);
  58 
  59     jobject dimension = (*env)->CallStaticObjectMethod(env, jc_Dimension, jm_getSize, axComponent, component);
  60     CHECK_EXCEPTION();
  61 
  62     if (dimension == NULL) return NSZeroSize;
  63     return NSMakeSize((*env)->GetIntField(env, dimension, jf_width), (*env)->GetIntField(env, dimension, jf_height));
  64 }
  65 
  66 NSString *getJavaRole(JNIEnv *env, jobject axComponent, jobject component)
  67 {
  68     GET_CACCESSIBILITY_CLASS_RETURN(nil);
  69     DECLARE_STATIC_METHOD_RETURN(sjm_getAccessibleRole, sjc_CAccessibility, "getAccessibleRole",
  70                            "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljava/lang/String;", nil);
  71     jobject axRole = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, sjm_getAccessibleRole,
  72                       axComponent, component);
  73     CHECK_EXCEPTION();
  74     if (axRole == NULL) return @"unknown";
  75 
  76     NSString* str = JavaStringToNSString(env, axRole);
  77     (*env)->DeleteLocalRef(env, axRole);
  78     return str;
  79 }
  80 
  81 jobject getAxSelection(JNIEnv *env, jobject axContext, jobject component)
  82 {
  83     GET_CACCESSIBILITY_CLASS_RETURN(nil);
  84     DECLARE_STATIC_METHOD_RETURN(jm_getAccessibleSelection, sjc_CAccessibility, "getAccessibleSelection",
  85             "(Ljavax/accessibility/AccessibleContext;Ljava/awt/Component;)Ljavax/accessibility/AccessibleSelection;", nil);
  86     jobject o = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, jm_getAccessibleSelection,
  87                       axContext, component);
  88     CHECK_EXCEPTION();
  89     return o;
  90 }
  91 
  92 jobject getAxContextSelection(JNIEnv *env, jobject axContext, jint index, jobject component)
  93 {
  94     GET_CACCESSIBILITY_CLASS_RETURN(nil);
  95     DECLARE_STATIC_METHOD_RETURN(jm_ax_getAccessibleSelection, sjc_CAccessibility, "ax_getAccessibleSelection",
  96                   "(Ljavax/accessibility/AccessibleContext;ILjava/awt/Component;)Ljavax/accessibility/Accessible;", nil);
  97     return (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, jm_ax_getAccessibleSelection,
  98                     axContext, index, component);
  99     CHECK_EXCEPTION();
 100 }
 101 
 102 void setAxContextSelection(JNIEnv *env, jobject axContext, jint index, jobject component)
 103 {
 104     GET_CACCESSIBILITY_CLASS();
 105     DECLARE_STATIC_METHOD(jm_addAccessibleSelection, sjc_CAccessibility, "addAccessibleSelection",
 106                    "(Ljavax/accessibility/AccessibleContext;ILjava/awt/Component;)V");
 107     (*env)->CallStaticVoidMethod(env, sjc_CAccessibility, jm_addAccessibleSelection,
 108                     axContext, index, component);
 109     CHECK_EXCEPTION();
 110 }
 111 
 112 jobject getAxContext(JNIEnv *env, jobject accessible, jobject component)
 113 {
 114     GET_CACCESSIBILITY_CLASS_RETURN(nil);
 115     DECLARE_STATIC_METHOD_RETURN(jm_getAccessibleContext, sjc_CAccessibility, "getAccessibleContext",
 116                "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljavax/accessibility/AccessibleContext;", nil);
 117     jobject o = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, jm_getAccessibleContext,
 118                     accessible, component);
 119     CHECK_EXCEPTION();
 120     return o;
 121 }
 122 
 123 BOOL isChildSelected(JNIEnv *env, jobject accessible, jint index, jobject component)
 124 {
 125     GET_CACCESSIBILITY_CLASS_RETURN(NO);
 126     DECLARE_STATIC_METHOD_RETURN(jm_isAccessibleChildSelected, sjc_CAccessibility, "isAccessibleChildSelected",
 127                 "(Ljavax/accessibility/Accessible;ILjava/awt/Component;)Z", NO);
 128     jboolean b = (*env)->CallStaticBooleanMethod(env, sjc_CAccessibility, jm_isAccessibleChildSelected,
 129                     accessible, index, component);
 130     CHECK_EXCEPTION();
 131     return b;
 132 }
 133 
 134 jobject getAxStateSet(JNIEnv *env, jobject axContext, jobject component)
 135 {
 136     GET_CACCESSIBILITY_CLASS_RETURN(nil);
 137     DECLARE_STATIC_METHOD_RETURN(jm_getAccessibleStateSet, sjc_CAccessibility, "getAccessibleStateSet",
 138                "(Ljavax/accessibility/AccessibleContext;Ljava/awt/Component;)Ljavax/accessibility/AccessibleStateSet;", nil);
 139     jobject o = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, jm_getAccessibleStateSet,
 140                     axContext, component);
 141     CHECK_EXCEPTION();
 142     return o;
 143 }
 144 
 145 BOOL containsAxState(JNIEnv *env, jobject axContext, jobject axState, jobject component)
 146 {
 147     GET_CACCESSIBILITY_CLASS_RETURN(NO);
 148     DECLARE_STATIC_METHOD_RETURN(jm_contains, sjc_CAccessibility, "contains",
 149                "(Ljavax/accessibility/AccessibleContext;Ljavax/accessibility/AccessibleState;Ljava/awt/Component;)Z", NO);
 150     jboolean b = (*env)->CallStaticBooleanMethod(env, sjc_CAccessibility, jm_contains, axContext, axState, component);
 151     CHECK_EXCEPTION();
 152     return b;
 153 }
 154 
 155 BOOL isVertical(JNIEnv *env, jobject axContext, jobject component)
 156 {
 157     GET_ACCESSIBLESTATE_CLASS_RETURN(NO);
 158     DECLARE_STATIC_FIELD_RETURN(jm_VERTICAL, sjc_AccessibleState, "VERTICAL", "Ljavax/accessibility/AccessibleState;", NO);
 159     jobject axVertState = (*env)->GetStaticObjectField(env, sjc_AccessibleState, jm_VERTICAL);
 160     CHECK_EXCEPTION_NULL_RETURN(axVertState, NO);
 161     BOOL vertical = containsAxState(env, axContext, axVertState, component);
 162     (*env)->DeleteLocalRef(env, axVertState);
 163     return vertical;
 164 }
 165 
 166 BOOL isHorizontal(JNIEnv *env, jobject axContext, jobject component)
 167 {
 168     GET_ACCESSIBLESTATE_CLASS_RETURN(NO);
 169     DECLARE_STATIC_FIELD_RETURN(jm_HORIZONTAL, sjc_AccessibleState, "HORIZONTAL", "Ljavax/accessibility/AccessibleState;", NO);
 170     jobject axHorizState = (*env)->GetStaticObjectField(env, sjc_AccessibleState, jm_HORIZONTAL);
 171     CHECK_EXCEPTION_NULL_RETURN(axHorizState, NO);
 172     BOOL horizontal = containsAxState(env, axContext, axHorizState, component);
 173     (*env)->DeleteLocalRef(env, axHorizState);
 174     return horizontal;
 175 }
 176 
 177 BOOL isShowing(JNIEnv *env, jobject axContext, jobject component)
 178 {
 179     GET_ACCESSIBLESTATE_CLASS_RETURN(NO);
 180     DECLARE_STATIC_FIELD_RETURN(jm_SHOWING, sjc_AccessibleState, "SHOWING", "Ljavax/accessibility/AccessibleState;", NO);
 181     jobject axVisibleState = (*env)->GetStaticObjectField(env, sjc_AccessibleState, jm_SHOWING);
 182     CHECK_EXCEPTION_NULL_RETURN(axVisibleState, NO);
 183     BOOL showing = containsAxState(env, axContext, axVisibleState, component);
 184     (*env)->DeleteLocalRef(env, axVisibleState);
 185     return showing;
 186 }
 187 
 188 BOOL isSelectable(JNIEnv *env, jobject axContext, jobject component)
 189 {
 190     GET_ACCESSIBLESTATE_CLASS_RETURN(NO);
 191     DECLARE_STATIC_FIELD_RETURN(jm_SELECTABLE,
 192                                     sjc_AccessibleState,
 193                                     "SELECTABLE",
 194                                     "Ljavax/accessibility/AccessibleState;", NO );
 195     jobject axSelectableState = (*env)->GetStaticObjectField(env, sjc_AccessibleState, jm_SELECTABLE);
 196     CHECK_EXCEPTION_NULL_RETURN(axSelectableState, NO);
 197     BOOL selectable = containsAxState(env, axContext, axSelectableState, component);
 198     (*env)->DeleteLocalRef(env, axSelectableState);
 199     return selectable;
 200 }
 201 
 202 NSPoint getAxComponentLocationOnScreen(JNIEnv *env, jobject axComponent, jobject component)
 203 {
 204     GET_CACCESSIBILITY_CLASS_RETURN(NSZeroPoint);
 205     DECLARE_STATIC_METHOD_RETURN(jm_getLocationOnScreen, sjc_CAccessibility, "getLocationOnScreen",
 206                   "(Ljavax/accessibility/AccessibleComponent;Ljava/awt/Component;)Ljava/awt/Point;", NSZeroPoint);
 207     DECLARE_CLASS_RETURN(sjc_Point, "java/awt/Point", NSZeroPoint);
 208     DECLARE_FIELD_RETURN(sjf_X, sjc_Point, "x", "I", NSZeroPoint);
 209     DECLARE_FIELD_RETURN(sjf_Y, sjc_Point, "y", "I", NSZeroPoint);
 210     jobject jpoint = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, jm_getLocationOnScreen,
 211                       axComponent, component);
 212     CHECK_EXCEPTION();
 213     if (jpoint == NULL) return NSZeroPoint;
 214     return NSMakePoint((*env)->GetIntField(env, jpoint, sjf_X), (*env)->GetIntField(env, jpoint, sjf_Y));
 215 }
 216 
 217 jint getAxTextCharCount(JNIEnv *env, jobject axText, jobject component)
 218 {
 219     GET_CACCESSIBILITY_CLASS_RETURN(0);
 220     DECLARE_STATIC_METHOD_RETURN(jm_getCharCount, sjc_CAccessibility, "getCharCount",
 221                   "(Ljavax/accessibility/AccessibleText;Ljava/awt/Component;)I", 0);
 222     int i = (*env)->CallStaticIntMethod(env, sjc_CAccessibility, jm_getCharCount, axText, component);
 223     CHECK_EXCEPTION();
 224     return i;
 225 }
 226 
 227 // The following JavaAccessibility methods are copied from the corresponding
 228 // NSAccessibility methods in NSAccessibility.m.
 229 //
 230 // They implement a key-value-like coding scheme to transform messages like
 231 //        [self accessibilityAttributeValue:NSAccessibilityEnabledAttribute]
 232 // into calls on to specific methods like
 233 //        [self accessibilityEnabledAttribute].
 234 
 235 static NSString *AttributeWithoutAXPrefix(NSString *attribute)
 236 {
 237     return [attribute hasPrefix:@"AX"] ? [attribute substringFromIndex:2] : attribute;
 238 }
 239 
 240 static SEL JavaAccessibilityAttributeGetter(NSString *attribute)
 241 {
 242     return NSSelectorFromString([NSString stringWithFormat:@"accessibility%@Attribute", AttributeWithoutAXPrefix(attribute)]);
 243 }
 244 
 245 static SEL JavaAccessibilityAttributeSettableTester(NSString *attribute)
 246 {
 247     return NSSelectorFromString([NSString stringWithFormat:@"accessibilityIs%@AttributeSettable", AttributeWithoutAXPrefix(attribute)]);
 248 }
 249 
 250 static SEL JavaAccessibilityAttributeSetter(NSString *attribute)
 251 {
 252     return NSSelectorFromString([NSString stringWithFormat:@"accessibilitySet%@Attribute:", AttributeWithoutAXPrefix(attribute)]);
 253 }
 254 
 255 id JavaAccessibilityAttributeValue(id element, NSString *attribute)
 256 {
 257     if (!JavaAccessibilityIsSupportedAttribute(element, attribute)) return nil;
 258 
 259     SEL getter = JavaAccessibilityAttributeGetter(attribute);
 260 #ifdef JAVA_AX_DEBUG_PARMS
 261     if (![element respondsToSelector:getter]) {
 262         JavaAccessibilityRaiseUnimplementedAttributeException(__FUNCTION__, element, attribute);
 263         return nil;
 264     }
 265 #endif
 266 
 267     return [element performSelector:getter];
 268 }
 269 
 270 BOOL JavaAccessibilityIsAttributeSettable(id element, NSString *attribute)
 271 {
 272     if (!JavaAccessibilityIsSupportedAttribute(element, attribute)) return NO;
 273 
 274     SEL tester = JavaAccessibilityAttributeSettableTester(attribute);
 275 #ifdef JAVA_AX_DEBUG_PARMS
 276     if (![element respondsToSelector:tester]) {
 277         JavaAccessibilityRaiseUnimplementedAttributeException(__FUNCTION__, element, attribute);
 278         return NO;
 279     }
 280 #endif
 281 
 282     return [element performSelector:tester] != nil;
 283 }
 284 
 285 void JavaAccessibilitySetAttributeValue(id element, NSString *attribute ,id value)
 286 {
 287     if (!JavaAccessibilityIsSupportedAttribute(element, attribute)) return;
 288 
 289     SEL setter = JavaAccessibilityAttributeSetter(attribute);
 290     if (![element accessibilityIsAttributeSettable:attribute]) return;
 291 
 292 #ifdef JAVA_AX_DEBUG_PARMS
 293     if (![element respondsToSelector:setter]) {
 294         JavaAccessibilityRaiseUnimplementedAttributeException(__FUNCTION__, element, attribute);
 295         return;
 296     }
 297 #endif
 298 
 299     [element performSelector:setter withObject:value];
 300 }
 301 
 302 static BOOL JavaAccessibilityIsSupportedAttribute(id element, NSString *attribute)
 303 {
 304     return [[element accessibilityAttributeNames] indexOfObject:attribute] != NSNotFound;
 305 }
 306 
 307 /*
 308  * Class:     sun_lwawt_macosx_CAccessibility
 309  * Method:    roleKey
 310  * Signature: (Ljavax/accessibility/AccessibleRole;)Ljava/lang/String;
 311  */
 312 JNIEXPORT jstring JNICALL Java_sun_lwawt_macosx_CAccessibility_roleKey
 313 (JNIEnv *env, jclass clz, jobject axRole)
 314 {
 315     DECLARE_CLASS_RETURN(sjc_AccessibleRole, "javax/accessibility/AccessibleRole", NULL);
 316     DECLARE_FIELD_RETURN(sjf_key, sjc_AccessibleRole, "key", "Ljava/lang/String;", NULL);
 317     return (*env)->GetObjectField(env, axRole, sjf_key);
 318 }
 319 
 320 
 321 // errors from NSAccessibilityErrors
 322 void JavaAccessibilityRaiseSetAttributeToIllegalTypeException(const char *functionName, id element, NSString *attribute, id value)
 323 {
 324     NSString *reason = [NSString stringWithFormat:@"%s: Attempt set \"%@\" attribute to illegal type of value (%@:%@) for element: %@", functionName, attribute, [value class], value, element];
 325     _JavaAccessibilityRaiseException(reason, kAXErrorIllegalArgument);
 326 }
 327 
 328 void JavaAccessibilityRaiseUnimplementedAttributeException(const char *functionName, id element, NSString *attribute)
 329 {
 330     NSString *reason = [NSString stringWithFormat:@"%s: \"%@\" attribute unimplemented by element: %@", functionName, attribute, element];
 331     _JavaAccessibilityRaiseException(reason, kAXErrorFailure);
 332 }
 333 
 334 void JavaAccessibilityRaiseIllegalParameterTypeException(const char *functionName, id element, NSString *attribute, id parameter)
 335 {
 336     NSString *reason = [NSString stringWithFormat:@"%s: \"%@\" parameterized attribute passed illegal type of parameter (%@:%@) for element: %@", functionName, attribute, [parameter class], parameter, element];
 337     _JavaAccessibilityRaiseException(reason, kAXErrorIllegalArgument);
 338 }
 339 
 340 static void _JavaAccessibilityRaiseException(NSString *reason, SInt32 errorCode)
 341 {
 342     JavaAccessibilityLogError(reason);
 343     [[NSException exceptionWithName:NSAccessibilityException reason:reason userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:errorCode], NSAccessibilityErrorCodeExceptionInfo, nil]] raise];
 344 }
 345 
 346 static void JavaAccessibilityLogError(NSString *message)
 347 {
 348     NSLog(@"!!! %@", message);
 349 }
 350 
 351 // end appKit copies
 352 
 353 /*
 354  To get the roles below, verify the perl has table below called macRoleCodes is correct.
 355  Then copy the perl code into a perl script called makeAxTables.pl (make
 356  sure to chmod +x makeAxTables.pl). Then run the perl script like this:
 357 
 358  ./makeAxTables.pl /Builds/jdk1_4_1/
 359 
 360  It will then write the void initializeRoles() method below to stdout.
 361 
 362  Any new AccessibleRole items that aren't in the perl hash table will be written out as follows:
 363  // Unknown AccessibleRole: <role>
 364 
 365  Add these unknowns to the perl hash table and re-run the script, and use the new generated table.
 366 */
 367 
 368 // NOTE: Don't modify this directly. It is machine generated. See below
 369 void initializeRoles()
 370 {
 371     sRoles = [[NSMutableDictionary alloc] initWithCapacity:56];
 372 
 373     [sRoles setObject:JavaAccessibilityIgnore forKey:@"alert"];
 374     [sRoles setObject:NSAccessibilityGroupRole forKey:@"awtcomponent"];
 375     [sRoles setObject:NSAccessibilityGroupRole forKey:@"canvas"];
 376     [sRoles setObject:NSAccessibilityCheckBoxRole forKey:@"checkbox"];
 377     [sRoles setObject:JavaAccessibilityIgnore forKey:@"colorchooser"];
 378     [sRoles setObject:NSAccessibilityColumnRole forKey:@"columnheader"];
 379     [sRoles setObject:NSAccessibilityComboBoxRole forKey:@"combobox"];
 380     [sRoles setObject:NSAccessibilityTextFieldRole forKey:@"dateeditor"];
 381     [sRoles setObject:NSAccessibilityImageRole forKey:@"desktopicon"];
 382     [sRoles setObject:JavaAccessibilityIgnore forKey:@"desktoppane"];
 383     [sRoles setObject:JavaAccessibilityIgnore forKey:@"dialog"];
 384     [sRoles setObject:JavaAccessibilityIgnore forKey:@"directorypane"];
 385     [sRoles setObject:JavaAccessibilityIgnore forKey:@"filechooser"];
 386     [sRoles setObject:JavaAccessibilityIgnore forKey:@"filler"];
 387     [sRoles setObject:JavaAccessibilityIgnore forKey:@"fontchooser"];
 388     [sRoles setObject:JavaAccessibilityIgnore forKey:@"frame"];
 389     [sRoles setObject:JavaAccessibilityIgnore forKey:@"glasspane"];
 390     [sRoles setObject:NSAccessibilityGroupRole forKey:@"groupbox"];
 391     [sRoles setObject:NSAccessibilityStaticTextRole forKey:@"hyperlink"]; //maybe a group?
 392     [sRoles setObject:NSAccessibilityImageRole forKey:@"icon"];
 393     [sRoles setObject:NSAccessibilityGroupRole forKey:@"internalframe"];
 394     [sRoles setObject:NSAccessibilityStaticTextRole forKey:@"label"];
 395     [sRoles setObject:JavaAccessibilityIgnore forKey:@"layeredpane"];
 396     [sRoles setObject:NSAccessibilityListRole forKey:@"list"]; // maybe a group? AccessibleRole.java says a list is: "An object that presents a list of objects to the user and allows the user to select one or more of them."
 397     [sRoles setObject:NSAccessibilityListRole forKey:@"listitem"];
 398     [sRoles setObject:NSAccessibilityMenuRole forKey:@"menu"];
 399     [sRoles setObject:NSAccessibilityMenuBarRole forKey:@"menubar"];
 400     [sRoles setObject:NSAccessibilityMenuItemRole forKey:@"menuitem"];
 401     [sRoles setObject:JavaAccessibilityIgnore forKey:@"optionpane"];
 402     [sRoles setObject:NSAccessibilityRadioButtonRole forKey:@"pagetab"]; // cmcnote: cocoa tabs are radio buttons - one selected button out of a group of options
 403     [sRoles setObject:NSAccessibilityTabGroupRole forKey:@"pagetablist"];
 404     [sRoles setObject:JavaAccessibilityIgnore forKey:@"panel"];
 405     [sRoles setObject:NSAccessibilityTextFieldRole forKey:@"passwordtext"];
 406     [sRoles setObject:NSAccessibilityPopUpButtonRole forKey:@"popupmenu"];
 407     [sRoles setObject:NSAccessibilityProgressIndicatorRole forKey:@"progressbar"];
 408     [sRoles setObject:NSAccessibilityButtonRole forKey:@"pushbutton"];
 409     [sRoles setObject:NSAccessibilityRadioButtonRole forKey:@"radiobutton"];
 410     [sRoles setObject:JavaAccessibilityIgnore forKey:@"rootpane"];
 411     [sRoles setObject:NSAccessibilityRowRole forKey:@"rowheader"];
 412     [sRoles setObject:NSAccessibilityScrollBarRole forKey:@"scrollbar"];
 413     [sRoles setObject:NSAccessibilityScrollAreaRole forKey:@"scrollpane"];
 414     [sRoles setObject:JavaAccessibilityIgnore forKey:@"separator"];
 415     [sRoles setObject:NSAccessibilitySliderRole forKey:@"slider"];
 416     [sRoles setObject:NSAccessibilityIncrementorRole forKey:@"spinbox"];
 417     [sRoles setObject:NSAccessibilitySplitGroupRole forKey:@"splitpane"];
 418     [sRoles setObject:NSAccessibilityValueIndicatorRole forKey:@"statusbar"];
 419     [sRoles setObject:NSAccessibilityGroupRole forKey:@"swingcomponent"];
 420     [sRoles setObject:NSAccessibilityTableRole forKey:@"table"];
 421     [sRoles setObject:NSAccessibilityTextFieldRole forKey:@"text"];
 422     [sRoles setObject:NSAccessibilityTextAreaRole forKey:@"textarea"]; // supports top/bottom of document notifications: CAccessability.getAccessibleRole()
 423     [sRoles setObject:NSAccessibilityCheckBoxRole forKey:@"togglebutton"];
 424     [sRoles setObject:NSAccessibilityToolbarRole forKey:@"toolbar"];
 425     [sRoles setObject:JavaAccessibilityIgnore forKey:@"tooltip"];
 426     [sRoles setObject:NSAccessibilityBrowserRole forKey:@"tree"];
 427     [sRoles setObject:NSAccessibilityUnknownRole forKey:@"unknown"];
 428     [sRoles setObject:JavaAccessibilityIgnore forKey:@"viewport"];
 429     [sRoles setObject:JavaAccessibilityIgnore forKey:@"window"];
 430 }