### Eclipse Workspace Patch 1.0 #P org.eclipse.swt Index: Eclipse SWT/carbon/org/eclipse/swt/widgets/Text.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.swt/Eclipse SWT/carbon/org/eclipse/swt/widgets/Text.java,v retrieving revision 1.151 diff -u -r1.151 Text.java --- Eclipse SWT/carbon/org/eclipse/swt/widgets/Text.java 13 May 2008 21:20:59 -0000 1.151 +++ Eclipse SWT/carbon/org/eclipse/swt/widgets/Text.java 19 May 2008 04:53:09 -0000 @@ -80,6 +80,15 @@ DELIMITER = "\r"; } + static final String [] AX_ATTRIBUTES = { + OS.kAXTitleAttribute, + OS.kAXValueAttribute, + OS.kAXNumberOfCharactersAttribute, + OS.kAXSelectedTextAttribute, + OS.kAXSelectedTextRangeAttribute, + OS.kAXStringForRangeParameterizedAttribute, + }; + /** * Constructs a new instance of this class given its parent * and a style value describing its behavior and appearance. @@ -681,6 +690,10 @@ return super.focusPart (); } +String [] getAxAttributes () { + return AX_ATTRIBUTES; +} + public int getBorderWidth () { checkWidget(); if (hasBorder ()) { @@ -1212,12 +1225,12 @@ return destY - (int) rect.y; } -String getTXNText (int iStartOffset, int iEndOffset) { +char [] getTXNChars (int iStartOffset, int iEndOffset) { int [] oDataHandle = new int [1]; OS.TXNGetData (txnObject, iStartOffset, iEndOffset, oDataHandle); - if (oDataHandle [0] == 0) return ""; + if (oDataHandle [0] == 0) return new char [0]; int length = OS.GetHandleSize (oDataHandle [0]); - if (length == 0) return ""; + if (length == 0) return new char [0]; int [] ptr = new int [1]; OS.HLock (oDataHandle [0]); OS.memmove (ptr, oDataHandle [0], 4); @@ -1225,7 +1238,11 @@ OS.memmove (buffer, ptr [0], length); OS.HUnlock (oDataHandle[0]); OS.DisposeHandle (oDataHandle[0]); - return new String (buffer); + return buffer; +} + +String getTXNText (int iStartOffset, int iEndOffset) { + return new String (getTXNChars (iStartOffset, iEndOffset)); } void hookEvents () { @@ -1336,6 +1353,95 @@ } } +int kEventAccessibleGetNamedAttribute (int nextHandler, int theEvent, int userData) { + int code = OS.eventNotHandledErr; + if (txnObject != 0) { + int [] stringRef = new int [1]; + OS.GetEventParameter (theEvent, OS.kEventParamAccessibleAttributeName, OS.typeCFStringRef, null, 4, null, stringRef); + int length = 0; + if (stringRef [0] != 0) length = OS.CFStringGetLength (stringRef [0]); + char [] buffer = new char [length]; + CFRange range = new CFRange (); + range.length = length; + OS.CFStringGetCharacters (stringRef [0], range, buffer); + String attributeName = new String(buffer); + if (attributeName.equals (OS.kAXRoleAttribute) || attributeName.equals (OS.kAXRoleDescriptionAttribute)) { + String roleText = (style & SWT.MULTI) != 0 ? OS.kAXTextAreaRole : OS.kAXTextFieldRole; + buffer = new char [roleText.length ()]; + roleText.getChars (0, buffer.length, buffer, 0); + stringRef [0] = OS.CFStringCreateWithCharacters (OS.kCFAllocatorDefault, buffer, buffer.length); + if (stringRef [0] != 0) { + if (attributeName.equals (OS.kAXRoleAttribute)) { + OS.SetEventParameter (theEvent, OS.kEventParamAccessibleAttributeValue, OS.typeCFStringRef, 4, stringRef); + } else { // kAXRoleDescriptionAttribute + int stringRef2 = OS.HICopyAccessibilityRoleDescription (stringRef [0], 0); + OS.SetEventParameter (theEvent, OS.kEventParamAccessibleAttributeValue, OS.typeCFStringRef, 4, new int [] {stringRef2}); + OS.CFRelease(stringRef2); + } + OS.CFRelease(stringRef [0]); + code = OS.noErr; + } + } else if (attributeName.equals (OS.kAXTitleAttribute)) { + /* + * Feature of the Macintosh. For some reason, AXTextFields return their text contents + * when they are asked for their title. Since they also return their text contents + * when they are asked for their value, this causes screen readers to speak the text + * twice. The fix is to return nothing when asked for a title. + */ + code = OS.noErr; + } else if (attributeName.equals (OS.kAXValueAttribute)) { + buffer = getTXNChars (OS.kTXNStartOffset, OS.kTXNEndOffset); + stringRef [0] = OS.CFStringCreateWithCharacters (OS.kCFAllocatorDefault, buffer, buffer.length); + if (stringRef [0] != 0) { + OS.SetEventParameter (theEvent, OS.kEventParamAccessibleAttributeValue, OS.typeCFStringRef, 4, stringRef); + OS.CFRelease(stringRef [0]); + code = OS.noErr; + } + } else if (attributeName.equals (OS.kAXNumberOfCharactersAttribute)) { + OS.SetEventParameter (theEvent, OS.kEventParamAccessibleAttributeValue, OS.typeSInt32, 4, new int [] {getCharCount()}); + code = OS.noErr; + } else if (attributeName.equals (OS.kAXSelectedTextAttribute)) { + Point sel = getSelection (); + buffer = getTXNChars (sel.x, sel.y); + stringRef [0] = OS.CFStringCreateWithCharacters (OS.kCFAllocatorDefault, buffer, buffer.length); + if (stringRef [0] != 0) { + OS.SetEventParameter (theEvent, OS.kEventParamAccessibleAttributeValue, OS.typeCFStringRef, 4, stringRef); + OS.CFRelease(stringRef [0]); + code = OS.noErr; + } + } else if (attributeName.equals (OS.kAXSelectedTextRangeAttribute)) { + Point sel = getSelection (); + range = new CFRange(); + range.location = sel.x; + range.length = sel.y - sel.x; + int valueRef = OS.AXValueCreate(OS.kAXValueCFRangeType, range); + OS.SetEventParameter (theEvent, OS.kEventParamAccessibleAttributeValue, OS.typeCFTypeRef, 4, new int [] {valueRef}); + OS.CFRelease(valueRef); + code = OS.noErr; + } else if (attributeName.equals (OS.kAXStringForRangeParameterizedAttribute)) { + int valueRef [] = new int [1]; + int status = OS.GetEventParameter (theEvent, OS.kEventParamAccessibleAttributeParameter, OS.typeCFTypeRef, null, 4, null, valueRef); + if (status == OS.noErr) { + range = new CFRange(); + boolean ok = OS.AXValueGetValue(valueRef[0], OS.kAXValueCFRangeType, range); + if (ok) { + buffer = getTXNChars (range.location, range.location + range.length); + stringRef [0] = OS.CFStringCreateWithCharacters (OS.kCFAllocatorDefault, buffer, buffer.length); + if (stringRef [0] != 0) { + OS.SetEventParameter (theEvent, OS.kEventParamAccessibleAttributeValue, OS.typeCFStringRef, 4, stringRef); + OS.CFRelease(stringRef [0]); + code = OS.noErr; + } + } + } + } + } + if (accessible != null) { + code = accessible.internal_kEventAccessibleGetNamedAttribute (nextHandler, theEvent, code); + } + return code; +} + int kEventMouseDown (int nextHandler, int theEvent, int userData) { int result = super.kEventMouseDown (nextHandler, theEvent, userData); if (result == OS.noErr) return result; @@ -1360,6 +1466,18 @@ int kEventUnicodeKeyPressed (int nextHandler, int theEvent, int userData) { int result = super.kEventUnicodeKeyPressed (nextHandler, theEvent, userData); if (result == OS.noErr) return result; + String string = OS.kAXSelectedTextChangedNotification; + char [] buffer = new char [string.length ()]; + string.getChars (0, buffer.length, buffer, 0); + int stringRef = OS.CFStringCreateWithCharacters (OS.kCFAllocatorDefault, buffer, buffer.length); + OS.AXNotificationHIObjectNotify(stringRef, handle, 0); + OS.CFRelease(stringRef); + string = OS.kAXValueChangedNotification; + buffer = new char [string.length ()]; + string.getChars (0, buffer.length, buffer, 0); + stringRef = OS.CFStringCreateWithCharacters (OS.kCFAllocatorDefault, buffer, buffer.length); + OS.AXNotificationHIObjectNotify(stringRef, handle, 0); + OS.CFRelease(stringRef); int [] keyboardEvent = new int [1]; OS.GetEventParameter (theEvent, OS.kEventParamTextInputSendKeyboardEvent, OS.typeEventRef, null, keyboardEvent.length * 4, null, keyboardEvent); int [] modifiers = new int [1];