< prev index next >

src/java.desktop/macosx/native/libawt_lwawt/awt/JavaTextAccessibility.m

Print this page
rev 54094 : 8257853: Remove dependencies on JNF's JNI utility functions in AWT and 2D code
rev 54095 : 8259343: [macOS] Update JNI error handling in Cocoa code.
rev 54098 : 8260616: Removing remaining JNF dependencies in the java.desktop module
8259729: Missed JNFInstanceOf -> IsInstanceOf conversion


  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 "JavaTextAccessibility.h"
  27 #import "JavaAccessibilityAction.h"
  28 #import "JavaAccessibilityUtilities.h"
  29 #import "ThreadUtilities.h"

  30 























  31 
  32 static JNF_CLASS_CACHE(sjc_CAccessibleText, "sun/lwawt/macosx/CAccessibleText");
  33 static JNF_STATIC_MEMBER_CACHE(sjm_getAccessibleText, sjc_CAccessibility, "getAccessibleText", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljavax/accessibility/AccessibleText;");
  34 static JNF_STATIC_MEMBER_CACHE(sjm_getAccessibleEditableText, sjc_CAccessibleText, "getAccessibleEditableText", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljavax/accessibility/AccessibleEditableText;");
  35 static JNF_STATIC_MEMBER_CACHE(sjm_getAccessibleName, sjc_CAccessibility, "getAccessibleName", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljava/lang/String;");
  36 
  37 /*
  38  * Converts an int array to an NSRange wrapped inside an NSValue
  39  * takes [start, end] values and returns [start, end - start]
  40  */
  41 NSValue *javaIntArrayToNSRangeValue(JNIEnv* env, jintArray array) {
  42     jint *values = (*env)->GetIntArrayElements(env, array, 0);
  43     if (values == NULL) {
  44         // Note: Java will not be on the stack here so a java exception can't happen and no need to call ExceptionCheck.
  45         NSLog(@"%s failed calling GetIntArrayElements", __FUNCTION__);
  46         return nil;
  47     };
  48     NSValue *value = [NSValue valueWithRange:NSMakeRange(values[0], values[1] - values[0])];
  49     (*env)->ReleaseIntArrayElements(env, array, values, 0);
  50     return value;
  51 }
  52 
  53 @implementation JavaTextAccessibility
  54 
  55 // based strongly upon NSTextViewAccessibility:accessibilityAttributeNames


  91             attributes = [[NSArray alloc] initWithObjects:
  92                 NSAccessibilityLineForIndexParameterizedAttribute,
  93                 NSAccessibilityRangeForLineParameterizedAttribute,
  94                 NSAccessibilityStringForRangeParameterizedAttribute,
  95                 NSAccessibilityRangeForPositionParameterizedAttribute,
  96                 NSAccessibilityRangeForIndexParameterizedAttribute,
  97                 NSAccessibilityBoundsForRangeParameterizedAttribute,
  98                 //NSAccessibilityRTFForRangeParameterizedAttribute, // cmcnote: not sure when/how these three are used. Investigate. radr://3960026
  99                 //NSAccessibilityStyleRangeForIndexParameterizedAttribute,
 100                 //NSAccessibilityAttributedStringForRangeParameterizedAttribute,
 101                 nil];
 102         }
 103         //APPKIT_UNLOCK;
 104     }
 105     return attributes;
 106 }
 107 
 108 - (NSString *)accessibilityValueAttribute
 109 {
 110     JNIEnv *env = [ThreadUtilities getJNIEnv];



 111     if ([[self accessibilityRoleAttribute] isEqualToString:NSAccessibilityStaticTextRole]) {
 112         // if it's static text, the AppKit AXValue is the java accessibleName
 113         jobject axName = JNFCallStaticObjectMethod(env, sjm_getAccessibleName, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)


 114         if (axName != NULL) {
 115             NSString* str = JNFJavaToNSString(env, axName);
 116             (*env)->DeleteLocalRef(env, axName);
 117             return str;
 118         }
 119         // value is still nil if no accessibleName for static text. Below, try to get the accessibleText.
 120     }
 121 
 122     // cmcnote: inefficient to make three distinct JNI calls. Coalesce. radr://3951923
 123     jobject axText = JNFCallStaticObjectMethod(env, sjm_getAccessibleText, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)



 124     if (axText == NULL) return nil;
 125     (*env)->DeleteLocalRef(env, axText);
 126 
 127     jobject axEditableText = JNFCallStaticObjectMethod(env, sjm_getAccessibleEditableText, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)



 128     if (axEditableText == NULL) return nil;
 129 
 130     static JNF_STATIC_MEMBER_CACHE(jm_getTextRange, sjc_CAccessibleText, "getTextRange", "(Ljavax/accessibility/AccessibleEditableText;IILjava/awt/Component;)Ljava/lang/String;");
 131     jobject jrange = JNFCallStaticObjectMethod(env, jm_getTextRange, axEditableText, 0, getAxTextCharCount(env, axEditableText, fComponent), fComponent);
 132     NSString *string = JNFJavaToNSString(env, jrange); // AWT_THREADING Safe (AWTRunLoop)



 133 
 134     (*env)->DeleteLocalRef(env, jrange);
 135     (*env)->DeleteLocalRef(env, axEditableText);
 136 
 137     if (string == nil) string = @"";
 138     return string;
 139 }
 140 
 141 - (BOOL)accessibilityIsValueAttributeSettable
 142 {
 143     // if text is enabled and editable, it's settable (according to NSCellTextAttributesAccessibility)
 144     BOOL isEnabled = [(NSNumber *)[self accessibilityEnabledAttribute] boolValue];
 145     if (!isEnabled) return NO;
 146 
 147     JNIEnv* env = [ThreadUtilities getJNIEnv];
 148     jobject axEditableText = JNFCallStaticObjectMethod(env, sjm_getAccessibleEditableText, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)



 149     if (axEditableText == NULL) return NO;
 150     (*env)->DeleteLocalRef(env, axEditableText);
 151     return YES;
 152 }
 153 
 154 - (void)accessibilitySetValueAttribute:(id)value
 155 {
 156 // cmcnote: should set the accessibleEditableText to the stringValue of value - AccessibleEditableText.setTextContents(String s)
 157 #ifdef JAVA_AX_DEBUG
 158     NSLog(@"Not yet implemented: %s\n", __FUNCTION__); // radr://3954018
 159 #endif
 160 }
 161 
 162 // Currently selected text (NSString)
 163 - (NSString *)accessibilitySelectedTextAttribute
 164 {
 165     JNIEnv* env = [ThreadUtilities getJNIEnv];
 166     static JNF_STATIC_MEMBER_CACHE(jm_getSelectedText, sjc_CAccessibleText, "getSelectedText", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljava/lang/String;");
 167     jobject axText = JNFCallStaticObjectMethod(env, jm_getSelectedText, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)




 168     if (axText == NULL) return @"";
 169     NSString* str = JNFJavaToNSString(env, axText);
 170     (*env)->DeleteLocalRef(env, axText);
 171     return str;
 172 }
 173 
 174 - (BOOL)accessibilityIsSelectedTextAttributeSettable
 175 {
 176     return YES; //cmcnote: for AXTextField that's selectable, it's settable. Investigate further.
 177 }
 178 
 179 - (void)accessibilitySetSelectedTextAttribute:(id)value
 180 {
 181 #ifdef JAVA_AX_DEBUG_PARMS
 182     if (![value isKindOfClass:[NSString class]]) {
 183         JavaAccessibilityRaiseSetAttributeToIllegalTypeException(__FUNCTION__, self, NSAccessibilitySelectedTextAttribute, value);
 184         return;
 185     }
 186 #endif
 187 
 188     JNIEnv *env = [ThreadUtilities getJNIEnv];
 189     jstring jstringValue = JNFNSToJavaString(env, (NSString *)value);
 190     static JNF_STATIC_MEMBER_CACHE(jm_setSelectedText, sjc_CAccessibleText, "setSelectedText", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;Ljava/lang/String;)V");
 191     JNFCallStaticVoidMethod(env, jm_setSelectedText, fAccessible, fComponent, jstringValue); // AWT_THREADING Safe (AWTRunLoop)




 192 }
 193 
 194 // Range of selected text (NSValue)
 195 - (NSValue *)accessibilitySelectedTextRangeAttribute
 196 {
 197     JNIEnv *env = [ThreadUtilities getJNIEnv];
 198     static JNF_STATIC_MEMBER_CACHE(jm_getSelectedTextRange, sjc_CAccessibleText, "getSelectedTextRange", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)[I");
 199     jintArray axTextRange = JNFCallStaticObjectMethod(env, jm_getSelectedTextRange, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)




 200     if (axTextRange == NULL) return nil;
 201 
 202     return javaIntArrayToNSRangeValue(env, axTextRange);
 203 }
 204 
 205 - (BOOL)accessibilityIsSelectedTextRangeAttributeSettable
 206 {
 207     return [(NSNumber *)[self accessibilityEnabledAttribute] boolValue]; // cmcnote: also may want to find out if isSelectable. Investigate.
 208 }
 209 
 210 - (void)accessibilitySetSelectedTextRangeAttribute:(id)value
 211 {
 212 #ifdef JAVA_AX_DEBUG_PARMS
 213     if (!([value isKindOfClass:[NSValue class]] && strcmp([(NSValue *)value objCType], @encode(NSRange)) == 0)) {
 214         JavaAccessibilityRaiseSetAttributeToIllegalTypeException(__FUNCTION__, self, NSAccessibilitySelectedTextRangeAttribute, value);
 215         return;
 216     }
 217 #endif
 218 
 219     NSRange range = [(NSValue *)value rangeValue];
 220     jint startIndex = range.location;
 221     jint endIndex = startIndex + range.length;
 222 
 223     JNIEnv *env = [ThreadUtilities getJNIEnv];
 224     static JNF_STATIC_MEMBER_CACHE(jm_setSelectedTextRange, sjc_CAccessibleText, "setSelectedTextRange", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;II)V");
 225     JNFCallStaticVoidMethod(env, jm_setSelectedTextRange, fAccessible, fComponent, startIndex, endIndex); // AWT_THREADING Safe (AWTRunLoop)




 226 }
 227 
 228 - (NSNumber *)accessibilityNumberOfCharactersAttribute
 229 {
 230     // cmcnote: should coalesce these two calls - radr://3951923
 231     // also, static text doesn't always have accessibleText. if axText is null, should get the charcount of the accessibleName instead
 232     JNIEnv *env = [ThreadUtilities getJNIEnv];
 233     jobject axText = JNFCallStaticObjectMethod(env, sjm_getAccessibleText, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)



 234     NSNumber* num = [NSNumber numberWithInt:getAxTextCharCount(env, axText, fComponent)];
 235     (*env)->DeleteLocalRef(env, axText);
 236     return num;
 237 }
 238 
 239 - (BOOL)accessibilityIsNumberOfCharactersAttributeSettable
 240 {
 241     return NO; // according to NSTextViewAccessibility.m and NSCellTextAttributesAccessibility.m
 242 }
 243 
 244 - (NSValue *)accessibilityVisibleCharacterRangeAttribute
 245 {
 246     JNIEnv *env = [ThreadUtilities getJNIEnv];
 247     static JNF_STATIC_MEMBER_CACHE(jm_getVisibleCharacterRange, sjc_CAccessibleText, "getVisibleCharacterRange", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)[I");
 248     jintArray axTextRange = JNFCallStaticObjectMethod(env, jm_getVisibleCharacterRange, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)




 249     if (axTextRange == NULL) return nil;
 250 
 251     return javaIntArrayToNSRangeValue(env, axTextRange);
 252 }
 253 
 254 - (BOOL)accessibilityIsVisibleCharacterRangeAttributeSettable
 255 {
 256 #ifdef JAVA_AX_DEBUG
 257     NSLog(@"Not yet implemented: %s\n", __FUNCTION__);
 258 #endif
 259     return NO;
 260 }
 261 
 262 - (NSValue *)accessibilityInsertionPointLineNumberAttribute
 263 {
 264     JNIEnv *env = [ThreadUtilities getJNIEnv];
 265     static JNF_STATIC_MEMBER_CACHE(jm_getLineNumberForInsertionPoint, sjc_CAccessibleText, "getLineNumberForInsertionPoint", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)I");
 266     jint row = JNFCallStaticIntMethod(env, jm_getLineNumberForInsertionPoint, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop)




 267     if (row < 0) return nil;
 268     return [NSNumber numberWithInt:row];
 269 }
 270 
 271 - (BOOL)accessibilityIsInsertionPointLineNumberAttributeSettable
 272 {
 273 #ifdef JAVA_AX_DEBUG
 274     NSLog(@"Not yet implemented: %s\n", __FUNCTION__);
 275 #endif
 276     return NO;
 277 }
 278 
 279 // parameterized attributes
 280 
 281 //
 282 // Usage of accessibilityBoundsForRangeAttributeForParameter:
 283 // ---
 284 // called by VoiceOver when interacting with text via ctrl-option-shift-downArrow.
 285 // Need to know bounding box for the character / word / line of interest in
 286 // order to draw VoiceOver cursor
 287 //
 288 - (NSValue *)accessibilityBoundsForRangeAttributeForParameter:(id)parameter
 289 {
 290 #ifdef JAVA_AX_DEBUG_PARMS
 291     if (!([parameter isKindOfClass:[NSValue class]] && strcmp([(NSValue *)parameter objCType], @encode(NSRange)) == 0)) {
 292         JavaAccessibilityRaiseIllegalParameterTypeException(__FUNCTION__, self, NSAccessibilityBoundsForRangeParameterizedAttribute, parameter);
 293         return nil;
 294     }
 295 #endif
 296 
 297     NSRange range = [(NSValue *)parameter rangeValue];
 298 
 299     JNIEnv *env = [ThreadUtilities getJNIEnv];
 300     static JNF_STATIC_MEMBER_CACHE(jm_getBoundsForRange, sjc_CAccessibleText, "getBoundsForRange", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;II)[D");
 301     jdoubleArray axBounds = (jdoubleArray)JNFCallStaticObjectMethod(env, jm_getBoundsForRange, fAccessible, fComponent, range.location, range.length); // AWT_THREADING Safe (AWTRunLoop)




 302     if (axBounds == NULL) return nil;
 303 
 304     // We cheat because we know that the array is 4 elements long (x, y, width, height)
 305     jdouble *values = (*env)->GetDoubleArrayElements(env, axBounds, 0);

 306     if (values == NULL) {
 307         // Note: Java will not be on the stack here so a java exception can't happen and no need to call ExceptionCheck.
 308         NSLog(@"%s failed calling GetDoubleArrayElements", __FUNCTION__);
 309         return nil;
 310     };
 311     NSRect bounds;
 312     bounds.origin.x = values[0];
 313     bounds.origin.y = [[[[self view] window] screen] frame].size.height - values[1] - values[3]; //values[1] is y-coord from top-left of screen. Flip. Account for the height (values[3]) when flipping
 314     bounds.size.width = values[2];
 315     bounds.size.height = values[3];
 316     NSValue *result = [NSValue valueWithRect:bounds];
 317     (*env)->ReleaseDoubleArrayElements(env, axBounds, values, 0);
 318     return result;
 319 }
 320 
 321 - (NSNumber *)accessibilityLineForIndexAttributeForParameter:(id)parameter
 322 {
 323     NSNumber *line = (NSNumber *) parameter;
 324     if (line == nil) return nil;
 325 
 326     JNIEnv *env = [ThreadUtilities getJNIEnv];
 327     static JNF_STATIC_MEMBER_CACHE(jm_getLineNumberForIndex, sjc_CAccessibleText, "getLineNumberForIndex", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;I)I");
 328     jint row = JNFCallStaticIntMethod(env, jm_getLineNumberForIndex, fAccessible, fComponent, [line intValue]); // AWT_THREADING Safe (AWTRunLoop)




 329     if (row < 0) return nil;
 330     return [NSNumber numberWithInt:row];
 331 }
 332 
 333 - (NSValue *)accessibilityRangeForLineAttributeForParameter:(id)parameter
 334 {
 335     NSNumber *line = (NSNumber *) parameter;
 336     if (line == nil) return nil;
 337 
 338     JNIEnv *env = [ThreadUtilities getJNIEnv];
 339     static JNF_STATIC_MEMBER_CACHE(jm_getRangeForLine, sjc_CAccessibleText, "getRangeForLine", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;I)[I");
 340     jintArray axTextRange = (jintArray)JNFCallStaticObjectMethod(env, jm_getRangeForLine, fAccessible, fComponent, [line intValue]); // AWT_THREADING Safe (AWTRunLoop)




 341     if (axTextRange == NULL) return nil;
 342 
 343     return javaIntArrayToNSRangeValue(env,axTextRange);
 344 }
 345 
 346 //
 347 // Usage of accessibilityStringForRangeAttributeForParameter:
 348 // ---
 349 // called by VoiceOver when interacting with text via ctrl-option-shift-downArrow.
 350 // VO needs to know the particular string its currently dealing with so it can
 351 // speak the string
 352 //
 353 - (NSString *)accessibilityStringForRangeAttributeForParameter:(id)parameter
 354 {
 355 #ifdef JAVA_AX_DEBUG_PARMS
 356     if (!([parameter isKindOfClass:[NSValue class]] && strcmp([(NSValue *)parameter objCType], @encode(NSRange)) == 0)) {
 357         JavaAccessibilityRaiseIllegalParameterTypeException(__FUNCTION__, self, NSAccessibilityBoundsForRangeParameterizedAttribute, parameter);
 358         return nil;
 359     }
 360 #endif
 361 
 362     NSRange range = [(NSValue *)parameter rangeValue];
 363 
 364     JNIEnv *env = [ThreadUtilities getJNIEnv];
 365     static JNF_STATIC_MEMBER_CACHE(jm_getStringForRange, sjc_CAccessibleText, "getStringForRange", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;II)Ljava/lang/String;");
 366     jstring jstringForRange = (jstring)JNFCallStaticObjectMethod(env, jm_getStringForRange, fAccessible, fComponent, range.location, range.length); // AWT_THREADING Safe (AWTRunLoop)
 367 



 368     if (jstringForRange == NULL) return @"";
 369     NSString* str = JNFJavaToNSString(env, jstringForRange);
 370     (*env)->DeleteLocalRef(env, jstringForRange);
 371     return str;
 372 }
 373 
 374 //
 375 // Usage of accessibilityRangeForPositionAttributeForParameter:
 376 // ---
 377 // cmcnote: I'm not sure when this is called / how it's used. Investigate.
 378 // probably could be used in a special text-only accessibilityHitTest to
 379 // find the index of the string under the mouse?
 380 //
 381 - (NSValue *)accessibilityRangeForPositionAttributeForParameter:(id)parameter
 382 {
 383 #ifdef JAVA_AX_DEBUG_PARMS
 384     if (!([parameter isKindOfClass:[NSValue class]] && strcmp([(NSValue *)parameter objCType], @encode(NSPoint)) == 0)) {
 385         JavaAccessibilityRaiseIllegalParameterTypeException(__FUNCTION__, self, NSAccessibilityRangeForPositionParameterizedAttribute, parameter);
 386         return nil;
 387     }
 388 #endif
 389 
 390     NSPoint point = [(NSValue *)parameter pointValue]; // point is in screen coords
 391     point.y = [[[[self view] window] screen] frame].size.height - point.y; // flip into java screen coords (0 is at upper-left corner of screen)
 392 
 393     JNIEnv *env = [ThreadUtilities getJNIEnv];
 394     static JNF_STATIC_MEMBER_CACHE(jm_getCharacterIndexAtPosition, sjc_CAccessibleText, "getCharacterIndexAtPosition", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;II)I");
 395     jint charIndex = JNFCallStaticIntMethod(env, jm_getCharacterIndexAtPosition, fAccessible, fComponent, point.x, point.y); // AWT_THREADING Safe (AWTRunLoop)




 396     if (charIndex == -1) return nil;
 397 
 398     // AccessibleText.getIndexAtPoint returns -1 for an invalid point
 399     NSRange range = NSMakeRange(charIndex, 1); //range's length is 1 - one-character range
 400     return [NSValue valueWithRange:range];
 401 }
 402 
 403 //
 404 // Usage of accessibilityRangeForIndexAttributeForParameter:
 405 // ---
 406 // cmcnote: I'm not sure when this is called / how it's used. Investigate.
 407 // AppKit version calls: [string rangeOfComposedCharacterSequenceAtIndex:index]
 408 // We call: CAccessibility.getRangeForIndex, which calls AccessibleText.getAtIndex(AccessibleText.WORD, index)
 409 // to determine the word closest to the given index. Then we find the length/location of this string.
 410 //
 411 - (NSValue *)accessibilityRangeForIndexAttributeForParameter:(id)parameter
 412 {
 413 #ifdef JAVA_AX_DEBUG_PARMS
 414     if (![parameter isKindOfClass:[NSNumber class]]) {
 415         JavaAccessibilityRaiseIllegalParameterTypeException(__FUNCTION__, self, NSAccessibilityRangeForIndexParameterizedAttribute, parameter);
 416         return nil;
 417     }
 418 #endif
 419 
 420     NSUInteger index = [(NSNumber *)parameter unsignedIntegerValue];
 421 
 422     JNIEnv *env = [ThreadUtilities getJNIEnv];
 423     static JNF_STATIC_MEMBER_CACHE(jm_getRangeForIndex, sjc_CAccessibleText, "getRangeForIndex", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;I)[I");
 424     jintArray axTextRange = (jintArray)JNFCallStaticObjectMethod(env, jm_getRangeForIndex, fAccessible, fComponent, index); // AWT_THREADING Safe (AWTRunLoop)




 425     if (axTextRange == NULL) return nil;
 426 
 427     return javaIntArrayToNSRangeValue(env, axTextRange);
 428 }
 429 
 430 /*
 431  * - (NSDictionary *)getActions:(JNIEnv *)env { ... }
 432  *
 433  * In the future, possibly add support: Editable text has AXShowMenu.
 434  * Textfields have AXConfirm.
 435  *
 436  * Note: JLabels (static text) in JLists have a press/click selection action
 437  *   which is currently handled in superclass JavaComponentAccessibility.
 438  *   If function is added here be sure to use [super getActions:env] for JLabels.
 439  */
 440 
 441 @end


  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 "JavaTextAccessibility.h"
  27 #import "JavaAccessibilityAction.h"
  28 #import "JavaAccessibilityUtilities.h"
  29 #import "ThreadUtilities.h"
  30 #import "JNIUtilities.h"
  31 
  32 static jclass sjc_CAccessibility = NULL;
  33 #define GET_CACCESSIBLITY_CLASS() \
  34      GET_CLASS(sjc_CAccessibility, "sun/lwawt/macosx/CAccessibility");
  35 #define GET_CACCESSIBLITY_CLASS_RETURN(ret) \
  36      GET_CLASS_RETURN(sjc_CAccessibility, "sun/lwawt/macosx/CAccessibility", ret);
  37 
  38 static jmethodID sjm_getAccessibleText = NULL;
  39 #define GET_ACCESSIBLETEXT_METHOD_RETURN(ret) \
  40     GET_CACCESSIBLITY_CLASS_RETURN(ret); \
  41     GET_STATIC_METHOD_RETURN(sjm_getAccessibleText, sjc_CAccessibility, "getAccessibleText", \
  42               "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljavax/accessibility/AccessibleText;", ret);
  43 
  44 static jclass sjc_CAccessibleText = NULL;
  45 #define GET_CACCESSIBLETEXT_CLASS() \
  46     GET_CLASS(sjc_CAccessibleText, "sun/lwawt/macosx/CAccessibleText");
  47 #define GET_CACCESSIBLETEXT_CLASS_RETURN(ret) \
  48     GET_CLASS_RETURN(sjc_CAccessibleText, "sun/lwawt/macosx/CAccessibleText", ret);
  49 
  50 static jmethodID sjm_getAccessibleEditableText = NULL;
  51 #define GET_ACCESSIBLEEDITABLETEXT_METHOD_RETURN(ret) \
  52     GET_CACCESSIBLETEXT_CLASS_RETURN(ret); \
  53     GET_STATIC_METHOD_RETURN(sjm_getAccessibleEditableText, sjc_CAccessibleText, "getAccessibleEditableText", \
  54               "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljavax/accessibility/AccessibleEditableText;", ret);
  55 




  56 
  57 /*
  58  * Converts an int array to an NSRange wrapped inside an NSValue
  59  * takes [start, end] values and returns [start, end - start]
  60  */
  61 NSValue *javaIntArrayToNSRangeValue(JNIEnv* env, jintArray array) {
  62     jint *values = (*env)->GetIntArrayElements(env, array, 0);
  63     if (values == NULL) {
  64         // Note: Java will not be on the stack here so a java exception can't happen and no need to call ExceptionCheck.
  65         NSLog(@"%s failed calling GetIntArrayElements", __FUNCTION__);
  66         return nil;
  67     };
  68     NSValue *value = [NSValue valueWithRange:NSMakeRange(values[0], values[1] - values[0])];
  69     (*env)->ReleaseIntArrayElements(env, array, values, 0);
  70     return value;
  71 }
  72 
  73 @implementation JavaTextAccessibility
  74 
  75 // based strongly upon NSTextViewAccessibility:accessibilityAttributeNames


 111             attributes = [[NSArray alloc] initWithObjects:
 112                 NSAccessibilityLineForIndexParameterizedAttribute,
 113                 NSAccessibilityRangeForLineParameterizedAttribute,
 114                 NSAccessibilityStringForRangeParameterizedAttribute,
 115                 NSAccessibilityRangeForPositionParameterizedAttribute,
 116                 NSAccessibilityRangeForIndexParameterizedAttribute,
 117                 NSAccessibilityBoundsForRangeParameterizedAttribute,
 118                 //NSAccessibilityRTFForRangeParameterizedAttribute, // cmcnote: not sure when/how these three are used. Investigate. radr://3960026
 119                 //NSAccessibilityStyleRangeForIndexParameterizedAttribute,
 120                 //NSAccessibilityAttributedStringForRangeParameterizedAttribute,
 121                 nil];
 122         }
 123         //APPKIT_UNLOCK;
 124     }
 125     return attributes;
 126 }
 127 
 128 - (NSString *)accessibilityValueAttribute
 129 {
 130     JNIEnv *env = [ThreadUtilities getJNIEnv];
 131     GET_CACCESSIBLITY_CLASS_RETURN(nil);
 132     DECLARE_STATIC_METHOD_RETURN(sjm_getAccessibleName, sjc_CAccessibility, "getAccessibleName",
 133                           "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljava/lang/String;", nil);
 134     if ([[self accessibilityRoleAttribute] isEqualToString:NSAccessibilityStaticTextRole]) {
 135         // if it's static text, the AppKit AXValue is the java accessibleName
 136         jobject axName = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility,
 137                            sjm_getAccessibleName, fAccessible, fComponent);
 138         CHECK_EXCEPTION();
 139         if (axName != NULL) {
 140             NSString* str = JavaStringToNSString(env, axName);
 141             (*env)->DeleteLocalRef(env, axName);
 142             return str;
 143         }
 144         // value is still nil if no accessibleName for static text. Below, try to get the accessibleText.
 145     }
 146 
 147     // cmcnote: inefficient to make three distinct JNI calls. Coalesce. radr://3951923
 148     GET_ACCESSIBLETEXT_METHOD_RETURN(@"");
 149     jobject axText = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility,
 150                       sjm_getAccessibleText, fAccessible, fComponent);
 151     CHECK_EXCEPTION();
 152     if (axText == NULL) return nil;
 153     (*env)->DeleteLocalRef(env, axText);
 154 
 155     GET_ACCESSIBLEEDITABLETEXT_METHOD_RETURN(nil);
 156     jobject axEditableText = (*env)->CallStaticObjectMethod(env, sjc_CAccessibleText,
 157                        sjm_getAccessibleEditableText, fAccessible, fComponent);
 158     CHECK_EXCEPTION();
 159     if (axEditableText == NULL) return nil;
 160 
 161     DECLARE_STATIC_METHOD_RETURN(jm_getTextRange, sjc_CAccessibleText, "getTextRange",
 162                     "(Ljavax/accessibility/AccessibleEditableText;IILjava/awt/Component;)Ljava/lang/String;", nil);
 163     jobject jrange = (*env)->CallStaticObjectMethod(env, sjc_CAccessibleText, jm_getTextRange,
 164                        axEditableText, 0, getAxTextCharCount(env, axEditableText, fComponent), fComponent);
 165     CHECK_EXCEPTION();
 166     NSString *string = JavaStringToNSString(env, jrange);
 167 
 168     (*env)->DeleteLocalRef(env, jrange);
 169     (*env)->DeleteLocalRef(env, axEditableText);
 170 
 171     if (string == nil) string = @"";
 172     return string;
 173 }
 174 
 175 - (BOOL)accessibilityIsValueAttributeSettable
 176 {
 177     // if text is enabled and editable, it's settable (according to NSCellTextAttributesAccessibility)
 178     BOOL isEnabled = [(NSNumber *)[self accessibilityEnabledAttribute] boolValue];
 179     if (!isEnabled) return NO;
 180 
 181     JNIEnv* env = [ThreadUtilities getJNIEnv];
 182     GET_ACCESSIBLEEDITABLETEXT_METHOD_RETURN(NO);
 183     jobject axEditableText = (*env)->CallStaticObjectMethod(env, sjc_CAccessibleText,
 184                      sjm_getAccessibleEditableText, fAccessible, fComponent);
 185     CHECK_EXCEPTION();
 186     if (axEditableText == NULL) return NO;
 187     (*env)->DeleteLocalRef(env, axEditableText);
 188     return YES;
 189 }
 190 
 191 - (void)accessibilitySetValueAttribute:(id)value
 192 {
 193 // cmcnote: should set the accessibleEditableText to the stringValue of value - AccessibleEditableText.setTextContents(String s)
 194 #ifdef JAVA_AX_DEBUG
 195     NSLog(@"Not yet implemented: %s\n", __FUNCTION__); // radr://3954018
 196 #endif
 197 }
 198 
 199 // Currently selected text (NSString)
 200 - (NSString *)accessibilitySelectedTextAttribute
 201 {
 202     JNIEnv* env = [ThreadUtilities getJNIEnv];
 203     GET_CACCESSIBLETEXT_CLASS_RETURN(nil);
 204     DECLARE_STATIC_METHOD_RETURN(jm_getSelectedText, sjc_CAccessibleText, "getSelectedText",
 205               "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljava/lang/String;", nil);
 206     jobject axText = (*env)->CallStaticObjectMethod(env, sjc_CAccessibleText, jm_getSelectedText,
 207                         fAccessible, fComponent);
 208     CHECK_EXCEPTION();
 209     if (axText == NULL) return @"";
 210     NSString* str = JavaStringToNSString(env, axText);
 211     (*env)->DeleteLocalRef(env, axText);
 212     return str;
 213 }
 214 
 215 - (BOOL)accessibilityIsSelectedTextAttributeSettable
 216 {
 217     return YES; //cmcnote: for AXTextField that's selectable, it's settable. Investigate further.
 218 }
 219 
 220 - (void)accessibilitySetSelectedTextAttribute:(id)value
 221 {
 222 #ifdef JAVA_AX_DEBUG_PARMS
 223     if (![value isKindOfClass:[NSString class]]) {
 224         JavaAccessibilityRaiseSetAttributeToIllegalTypeException(__FUNCTION__, self, NSAccessibilitySelectedTextAttribute, value);
 225         return;
 226     }
 227 #endif
 228 
 229     JNIEnv *env = [ThreadUtilities getJNIEnv];
 230     jstring jstringValue = NSStringToJavaString(env, (NSString *)value);
 231     GET_CACCESSIBLETEXT_CLASS();
 232     DECLARE_STATIC_METHOD(jm_setSelectedText, sjc_CAccessibleText, "setSelectedText",
 233                    "(Ljavax/accessibility/Accessible;Ljava/awt/Component;Ljava/lang/String;)V");
 234     (*env)->CallStaticVoidMethod(env, sjc_CAccessibleText, jm_setSelectedText,
 235               fAccessible, fComponent, jstringValue);
 236     CHECK_EXCEPTION();
 237 }
 238 
 239 // Range of selected text (NSValue)
 240 - (NSValue *)accessibilitySelectedTextRangeAttribute
 241 {
 242     JNIEnv *env = [ThreadUtilities getJNIEnv];
 243     GET_CACCESSIBLETEXT_CLASS_RETURN(nil);
 244     DECLARE_STATIC_METHOD_RETURN(jm_getSelectedTextRange, sjc_CAccessibleText, "getSelectedTextRange",
 245            "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)[I", nil);
 246     jintArray axTextRange = (*env)->CallStaticObjectMethod(env, sjc_CAccessibleText,
 247                 jm_getSelectedTextRange, fAccessible, fComponent);
 248     CHECK_EXCEPTION();
 249     if (axTextRange == NULL) return nil;
 250 
 251     return javaIntArrayToNSRangeValue(env, axTextRange);
 252 }
 253 
 254 - (BOOL)accessibilityIsSelectedTextRangeAttributeSettable
 255 {
 256     return [(NSNumber *)[self accessibilityEnabledAttribute] boolValue]; // cmcnote: also may want to find out if isSelectable. Investigate.
 257 }
 258 
 259 - (void)accessibilitySetSelectedTextRangeAttribute:(id)value
 260 {
 261 #ifdef JAVA_AX_DEBUG_PARMS
 262     if (!([value isKindOfClass:[NSValue class]] && strcmp([(NSValue *)value objCType], @encode(NSRange)) == 0)) {
 263         JavaAccessibilityRaiseSetAttributeToIllegalTypeException(__FUNCTION__, self, NSAccessibilitySelectedTextRangeAttribute, value);
 264         return;
 265     }
 266 #endif
 267 
 268     NSRange range = [(NSValue *)value rangeValue];
 269     jint startIndex = range.location;
 270     jint endIndex = startIndex + range.length;
 271 
 272     JNIEnv *env = [ThreadUtilities getJNIEnv];
 273     GET_CACCESSIBLETEXT_CLASS();
 274     DECLARE_STATIC_METHOD(jm_setSelectedTextRange, sjc_CAccessibleText, "setSelectedTextRange",
 275                   "(Ljavax/accessibility/Accessible;Ljava/awt/Component;II)V");
 276     (*env)->CallStaticVoidMethod(env, sjc_CAccessibleText, jm_setSelectedTextRange,
 277                   fAccessible, fComponent, startIndex, endIndex);
 278     CHECK_EXCEPTION();
 279 }
 280 
 281 - (NSNumber *)accessibilityNumberOfCharactersAttribute
 282 {
 283     // cmcnote: should coalesce these two calls - radr://3951923
 284     // also, static text doesn't always have accessibleText. if axText is null, should get the charcount of the accessibleName instead
 285     JNIEnv *env = [ThreadUtilities getJNIEnv];
 286     GET_ACCESSIBLETEXT_METHOD_RETURN(nil);
 287     jobject axText = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility,
 288                      sjm_getAccessibleText, fAccessible, fComponent);
 289     CHECK_EXCEPTION();
 290     NSNumber* num = [NSNumber numberWithInt:getAxTextCharCount(env, axText, fComponent)];
 291     (*env)->DeleteLocalRef(env, axText);
 292     return num;
 293 }
 294 
 295 - (BOOL)accessibilityIsNumberOfCharactersAttributeSettable
 296 {
 297     return NO; // according to NSTextViewAccessibility.m and NSCellTextAttributesAccessibility.m
 298 }
 299 
 300 - (NSValue *)accessibilityVisibleCharacterRangeAttribute
 301 {
 302     JNIEnv *env = [ThreadUtilities getJNIEnv];
 303     GET_CACCESSIBLETEXT_CLASS_RETURN(nil);
 304     DECLARE_STATIC_METHOD_RETURN(jm_getVisibleCharacterRange, sjc_CAccessibleText, "getVisibleCharacterRange",
 305                           "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)[I", nil);
 306     jintArray axTextRange = (*env)->CallStaticObjectMethod(env, sjc_CAccessibleText,
 307                  jm_getVisibleCharacterRange, fAccessible, fComponent);
 308     CHECK_EXCEPTION();
 309     if (axTextRange == NULL) return nil;
 310 
 311     return javaIntArrayToNSRangeValue(env, axTextRange);
 312 }
 313 
 314 - (BOOL)accessibilityIsVisibleCharacterRangeAttributeSettable
 315 {
 316 #ifdef JAVA_AX_DEBUG
 317     NSLog(@"Not yet implemented: %s\n", __FUNCTION__);
 318 #endif
 319     return NO;
 320 }
 321 
 322 - (NSValue *)accessibilityInsertionPointLineNumberAttribute
 323 {
 324     JNIEnv *env = [ThreadUtilities getJNIEnv];
 325     GET_CACCESSIBLETEXT_CLASS_RETURN(nil);
 326     DECLARE_STATIC_METHOD_RETURN(jm_getLineNumberForInsertionPoint, sjc_CAccessibleText,
 327              "getLineNumberForInsertionPoint", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)I", nil);
 328     jint row = (*env)->CallStaticIntMethod(env, sjc_CAccessibleText,
 329                   jm_getLineNumberForInsertionPoint, fAccessible, fComponent);
 330     CHECK_EXCEPTION();
 331     if (row < 0) return nil;
 332     return [NSNumber numberWithInt:row];
 333 }
 334 
 335 - (BOOL)accessibilityIsInsertionPointLineNumberAttributeSettable
 336 {
 337 #ifdef JAVA_AX_DEBUG
 338     NSLog(@"Not yet implemented: %s\n", __FUNCTION__);
 339 #endif
 340     return NO;
 341 }
 342 
 343 // parameterized attributes
 344 
 345 //
 346 // Usage of accessibilityBoundsForRangeAttributeForParameter:
 347 // ---
 348 // called by VoiceOver when interacting with text via ctrl-option-shift-downArrow.
 349 // Need to know bounding box for the character / word / line of interest in
 350 // order to draw VoiceOver cursor
 351 //
 352 - (NSValue *)accessibilityBoundsForRangeAttributeForParameter:(id)parameter
 353 {
 354 #ifdef JAVA_AX_DEBUG_PARMS
 355     if (!([parameter isKindOfClass:[NSValue class]] && strcmp([(NSValue *)parameter objCType], @encode(NSRange)) == 0)) {
 356         JavaAccessibilityRaiseIllegalParameterTypeException(__FUNCTION__, self, NSAccessibilityBoundsForRangeParameterizedAttribute, parameter);
 357         return nil;
 358     }
 359 #endif
 360 
 361     NSRange range = [(NSValue *)parameter rangeValue];
 362 
 363     JNIEnv *env = [ThreadUtilities getJNIEnv];
 364     GET_CACCESSIBLETEXT_CLASS_RETURN(nil);
 365     DECLARE_STATIC_METHOD_RETURN(jm_getBoundsForRange, sjc_CAccessibleText, "getBoundsForRange",
 366                          "(Ljavax/accessibility/Accessible;Ljava/awt/Component;II)[D", nil);
 367     jdoubleArray axBounds = (jdoubleArray)(*env)->CallStaticObjectMethod(env, sjc_CAccessibleText, jm_getBoundsForRange,
 368                               fAccessible, fComponent, range.location, range.length);
 369     CHECK_EXCEPTION();
 370     if (axBounds == NULL) return nil;
 371 
 372     // We cheat because we know that the array is 4 elements long (x, y, width, height)
 373     jdouble *values = (*env)->GetDoubleArrayElements(env, axBounds, 0);
 374     CHECK_EXCEPTION();
 375     if (values == NULL) {
 376         // Note: Java will not be on the stack here so a java exception can't happen and no need to call ExceptionCheck.
 377         NSLog(@"%s failed calling GetDoubleArrayElements", __FUNCTION__);
 378         return nil;
 379     };
 380     NSRect bounds;
 381     bounds.origin.x = values[0];
 382     bounds.origin.y = [[[[self view] window] screen] frame].size.height - values[1] - values[3]; //values[1] is y-coord from top-left of screen. Flip. Account for the height (values[3]) when flipping
 383     bounds.size.width = values[2];
 384     bounds.size.height = values[3];
 385     NSValue *result = [NSValue valueWithRect:bounds];
 386     (*env)->ReleaseDoubleArrayElements(env, axBounds, values, 0);
 387     return result;
 388 }
 389 
 390 - (NSNumber *)accessibilityLineForIndexAttributeForParameter:(id)parameter
 391 {
 392     NSNumber *line = (NSNumber *) parameter;
 393     if (line == nil) return nil;
 394 
 395     JNIEnv *env = [ThreadUtilities getJNIEnv];
 396     GET_CACCESSIBLETEXT_CLASS_RETURN(nil);
 397     DECLARE_STATIC_METHOD_RETURN(jm_getLineNumberForIndex, sjc_CAccessibleText, "getLineNumberForIndex",
 398                            "(Ljavax/accessibility/Accessible;Ljava/awt/Component;I)I", nil);
 399     jint row = (*env)->CallStaticIntMethod(env, sjc_CAccessibleText, jm_getLineNumberForIndex,
 400                        fAccessible, fComponent, [line intValue]);
 401     CHECK_EXCEPTION();
 402     if (row < 0) return nil;
 403     return [NSNumber numberWithInt:row];
 404 }
 405 
 406 - (NSValue *)accessibilityRangeForLineAttributeForParameter:(id)parameter
 407 {
 408     NSNumber *line = (NSNumber *) parameter;
 409     if (line == nil) return nil;
 410 
 411     JNIEnv *env = [ThreadUtilities getJNIEnv];
 412     GET_CACCESSIBLETEXT_CLASS_RETURN(nil);
 413     DECLARE_STATIC_METHOD_RETURN(jm_getRangeForLine, sjc_CAccessibleText, "getRangeForLine",
 414                  "(Ljavax/accessibility/Accessible;Ljava/awt/Component;I)[I", nil);
 415     jintArray axTextRange = (jintArray)(*env)->CallStaticObjectMethod(env, sjc_CAccessibleText,
 416                 jm_getRangeForLine, fAccessible, fComponent, [line intValue]);
 417     CHECK_EXCEPTION();
 418     if (axTextRange == NULL) return nil;
 419 
 420     return javaIntArrayToNSRangeValue(env,axTextRange);
 421 }
 422 
 423 //
 424 // Usage of accessibilityStringForRangeAttributeForParameter:
 425 // ---
 426 // called by VoiceOver when interacting with text via ctrl-option-shift-downArrow.
 427 // VO needs to know the particular string its currently dealing with so it can
 428 // speak the string
 429 //
 430 - (NSString *)accessibilityStringForRangeAttributeForParameter:(id)parameter
 431 {
 432 #ifdef JAVA_AX_DEBUG_PARMS
 433     if (!([parameter isKindOfClass:[NSValue class]] && strcmp([(NSValue *)parameter objCType], @encode(NSRange)) == 0)) {
 434         JavaAccessibilityRaiseIllegalParameterTypeException(__FUNCTION__, self, NSAccessibilityBoundsForRangeParameterizedAttribute, parameter);
 435         return nil;
 436     }
 437 #endif
 438 
 439     NSRange range = [(NSValue *)parameter rangeValue];
 440 
 441     JNIEnv *env = [ThreadUtilities getJNIEnv];
 442     GET_CACCESSIBLETEXT_CLASS_RETURN(nil);
 443     DECLARE_STATIC_METHOD_RETURN(jm_getStringForRange, sjc_CAccessibleText, "getStringForRange",
 444                  "(Ljavax/accessibility/Accessible;Ljava/awt/Component;II)Ljava/lang/String;", nil);
 445     jstring jstringForRange = (jstring)(*env)->CallStaticObjectMethod(env, sjc_CAccessibleText, jm_getStringForRange,
 446                             fAccessible, fComponent, range.location, range.length);
 447     CHECK_EXCEPTION();
 448     if (jstringForRange == NULL) return @"";
 449     NSString* str = JavaStringToNSString(env, jstringForRange);
 450     (*env)->DeleteLocalRef(env, jstringForRange);
 451     return str;
 452 }
 453 
 454 //
 455 // Usage of accessibilityRangeForPositionAttributeForParameter:
 456 // ---
 457 // cmcnote: I'm not sure when this is called / how it's used. Investigate.
 458 // probably could be used in a special text-only accessibilityHitTest to
 459 // find the index of the string under the mouse?
 460 //
 461 - (NSValue *)accessibilityRangeForPositionAttributeForParameter:(id)parameter
 462 {
 463 #ifdef JAVA_AX_DEBUG_PARMS
 464     if (!([parameter isKindOfClass:[NSValue class]] && strcmp([(NSValue *)parameter objCType], @encode(NSPoint)) == 0)) {
 465         JavaAccessibilityRaiseIllegalParameterTypeException(__FUNCTION__, self, NSAccessibilityRangeForPositionParameterizedAttribute, parameter);
 466         return nil;
 467     }
 468 #endif
 469 
 470     NSPoint point = [(NSValue *)parameter pointValue]; // point is in screen coords
 471     point.y = [[[[self view] window] screen] frame].size.height - point.y; // flip into java screen coords (0 is at upper-left corner of screen)
 472 
 473     JNIEnv *env = [ThreadUtilities getJNIEnv];
 474     GET_CACCESSIBLETEXT_CLASS_RETURN(nil);
 475     DECLARE_STATIC_METHOD_RETURN(jm_getCharacterIndexAtPosition, sjc_CAccessibleText, "getCharacterIndexAtPosition",
 476                            "(Ljavax/accessibility/Accessible;Ljava/awt/Component;II)I", nil);
 477     jint charIndex = (*env)->CallStaticIntMethod(env, sjc_CAccessibleText, jm_getCharacterIndexAtPosition,
 478                             fAccessible, fComponent, point.x, point.y);
 479     CHECK_EXCEPTION();
 480     if (charIndex == -1) return nil;
 481 
 482     // AccessibleText.getIndexAtPoint returns -1 for an invalid point
 483     NSRange range = NSMakeRange(charIndex, 1); //range's length is 1 - one-character range
 484     return [NSValue valueWithRange:range];
 485 }
 486 
 487 //
 488 // Usage of accessibilityRangeForIndexAttributeForParameter:
 489 // ---
 490 // cmcnote: I'm not sure when this is called / how it's used. Investigate.
 491 // AppKit version calls: [string rangeOfComposedCharacterSequenceAtIndex:index]
 492 // We call: CAccessibility.getRangeForIndex, which calls AccessibleText.getAtIndex(AccessibleText.WORD, index)
 493 // to determine the word closest to the given index. Then we find the length/location of this string.
 494 //
 495 - (NSValue *)accessibilityRangeForIndexAttributeForParameter:(id)parameter
 496 {
 497 #ifdef JAVA_AX_DEBUG_PARMS
 498     if (![parameter isKindOfClass:[NSNumber class]]) {
 499         JavaAccessibilityRaiseIllegalParameterTypeException(__FUNCTION__, self, NSAccessibilityRangeForIndexParameterizedAttribute, parameter);
 500         return nil;
 501     }
 502 #endif
 503 
 504     NSUInteger index = [(NSNumber *)parameter unsignedIntegerValue];
 505 
 506     JNIEnv *env = [ThreadUtilities getJNIEnv];
 507     GET_CACCESSIBLETEXT_CLASS_RETURN(nil);
 508     DECLARE_STATIC_METHOD_RETURN(jm_getRangeForIndex, sjc_CAccessibleText, "getRangeForIndex",
 509                     "(Ljavax/accessibility/Accessible;Ljava/awt/Component;I)[I", nil);
 510     jintArray axTextRange = (jintArray)(*env)->CallStaticObjectMethod(env, sjc_CAccessibleText, jm_getRangeForIndex,
 511                               fAccessible, fComponent, index);
 512     CHECK_EXCEPTION();
 513     if (axTextRange == NULL) return nil;
 514 
 515     return javaIntArrayToNSRangeValue(env, axTextRange);
 516 }
 517 
 518 /*
 519  * - (NSDictionary *)getActions:(JNIEnv *)env { ... }
 520  *
 521  * In the future, possibly add support: Editable text has AXShowMenu.
 522  * Textfields have AXConfirm.
 523  *
 524  * Note: JLabels (static text) in JLists have a press/click selection action
 525  *   which is currently handled in superclass JavaComponentAccessibility.
 526  *   If function is added here be sure to use [super getActions:env] for JLabels.
 527  */
 528 
 529 @end
< prev index next >