MGR: Fix ProjectListCtrl accessibility code bug, clean up Mac accessibility code

svn path=/trunk/boinc/; revision=21886
This commit is contained in:
Charlie Fenton 2010-07-09 10:18:48 +00:00
parent d866180ece
commit 922a232a7f
6 changed files with 117 additions and 536 deletions

View File

@ -4981,3 +4981,13 @@ David 8 Jul 2010
client_msgs.cpp
win_build/
boinc.sln
Charlie 9 Jul 2010
- MGR: Fix accessibility code bug in Attach Wizard's ProjectListCtrl,
consolidate and clean up Mac accessibility code.
clientgui/
NoticeListCtrl.cpp, .h
ProjectListCtrl.cpp, .h
mac/
MacAccessiblity.cpp

View File

@ -28,8 +28,12 @@
////@begin XPM images
////@end XPM images
#if wxUSE_ACCESSIBILITY || defined(__WXMAC__)
#ifdef __WXMAC__
IMPLEMENT_CLASS( CNoticeListCtrlAccessible, wxObject )
CNoticeListCtrlAccessible::CNoticeListCtrlAccessible(wxWindow* win) {
mp_win = win;
SetupMacAccessibilitySupport();
@ -42,8 +46,6 @@ CNoticeListCtrlAccessible::~CNoticeListCtrlAccessible() {
#endif
#if wxUSE_ACCESSIBILITY || defined(__WXMAC__)
// Gets the name of the specified object.
wxAccStatus CNoticeListCtrlAccessible::GetName(int childId, wxString* name)
{

View File

@ -46,6 +46,8 @@ public:
#ifndef __WXMAC__
CNoticeListCtrlAccessible(wxWindow* win): wxWindowAccessible(win) {}
#else
DECLARE_CLASS( CNoticeListCtrlAccessible )
CNoticeListCtrlAccessible(wxWindow* win);
virtual ~CNoticeListCtrlAccessible();
#endif

View File

@ -32,8 +32,12 @@
////@end XPM images
#if wxUSE_ACCESSIBILITY || defined(__WXMAC__)
#ifdef __WXMAC__
IMPLEMENT_CLASS( CProjectListCtrlAccessible, wxObject )
CProjectListCtrlAccessible::CProjectListCtrlAccessible(wxWindow* win) {
mp_win = win;
SetupMacAccessibilitySupport();
@ -46,8 +50,6 @@ CProjectListCtrlAccessible::~CProjectListCtrlAccessible() {
#endif
#if wxUSE_ACCESSIBILITY || defined(__WXMAC__)
// Gets the name of the specified object.
wxAccStatus CProjectListCtrlAccessible::GetName(int childId, wxString* name)
{
@ -98,25 +100,21 @@ wxAccStatus CProjectListCtrlAccessible::GetLocation(wxRect& rect, int elementId)
{
// List item
wxSize cCtrlSize = pCtrl->GetClientSize();
int iItemWidth = cCtrlSize.GetWidth();
int iItemHeight = pCtrl->GetTotalClientHeight() / (int)pCtrl->GetItemCount();
// Set the initial control postition to the absolute coords of the upper
// left hand position of the control
rect.SetPosition(pCtrl->GetScreenPosition());
rect.width = iItemWidth - 1;
rect.height = iItemHeight - 1;
rect.width = cCtrlSize.GetWidth() - 1;
rect.height = pCtrl->GetItemHeight(elementId - 1) - 1;
if (1 == elementId)
{
// First child
}
else
{
// Other children
rect.SetTop(rect.GetTop() + ((elementId - 1) * iItemHeight) + 1);
rect.height -= 1;
// Items can have different heights
int firstVisibleItem = (int)pCtrl->GetFirstVisibleLine();
int yOffset = 0;
for (int i=firstVisibleItem; i<(elementId - 1); ++i) {
yOffset += pCtrl->GetItemHeight((size_t)i);
}
rect.SetTop(rect.GetTop() + yOffset);
rect.height -= 1;
return wxACC_OK;
}
// Let the framework handle the other cases.
@ -606,14 +604,3 @@ CProjectListItem* CProjectListCtrl::GetItem(
{
return m_Items[iIndex];
}
/*!
* Return the total height of all the client items.
*/
wxCoord CProjectListCtrl::GetTotalClientHeight()
{
return EstimateTotalHeight();
}

View File

@ -94,6 +94,8 @@ class CProjectListCtrlAccessible: public wxWindowAccessible
public:
#ifdef __WXMAC__
DECLARE_CLASS( CProjectListCtrlAccessible )
CProjectListCtrlAccessible(wxWindow* win);
virtual ~CProjectListCtrlAccessible();
#else
@ -162,6 +164,8 @@ public:
virtual wxString OnGetItem(size_t i) const;
int GetItemHeight(size_t i) { return (int)OnMeasureItem(i); }
/// Methods
bool Append(
wxString strURL,
@ -178,8 +182,6 @@ public:
int iIndex
);
wxCoord GetTotalClientHeight();
private:
std::vector<CProjectListItem*> m_Items;

View File

@ -71,10 +71,7 @@ void AccessibilityIgnoreAllChildren(HIViewRef parent, int recursionLevel) {
pascal OSStatus BOINCListAccessibilityEventHandler( EventHandlerCallRef inHandlerCallRef,
EventRef inEvent, void* pData);
pascal OSStatus AttachListAccessibilityEventHandler( EventHandlerCallRef inHandlerCallRef,
EventRef inEvent, void* pData);
pascal OSStatus NoticeListAccessibilityEventHandler( EventHandlerCallRef inHandlerCallRef,
pascal OSStatus HTMLListAccessibilityEventHandler( EventHandlerCallRef inHandlerCallRef,
EventRef inEvent, void* pData);
static EventTypeSpec myAccessibilityEvents[] = {
@ -198,7 +195,7 @@ void CProjectListCtrlAccessible::SetupMacAccessibilitySupport() {
m_listView = (HIViewRef)pCtrl->GetHandle();
err = HIViewSetEnabled(m_listView, true);
err = InstallHIObjectEventHandler((HIObjectRef)m_listView, NewEventHandlerUPP(AttachListAccessibilityEventHandler),
err = InstallHIObjectEventHandler((HIObjectRef)m_listView, NewEventHandlerUPP(HTMLListAccessibilityEventHandler),
sizeof(myAccessibilityEvents) / sizeof(EventTypeSpec), myAccessibilityEvents,
this, &m_plistAccessibilityEventHandlerRef);
} else {
@ -226,7 +223,7 @@ void CNoticeListCtrlAccessible::SetupMacAccessibilitySupport() {
m_listView = (HIViewRef)pCtrl->GetHandle();
err = HIViewSetEnabled(m_listView, true);
err = InstallHIObjectEventHandler((HIObjectRef)m_listView, NewEventHandlerUPP(NoticeListAccessibilityEventHandler),
err = InstallHIObjectEventHandler((HIObjectRef)m_listView, NewEventHandlerUPP(HTMLListAccessibilityEventHandler),
sizeof(myAccessibilityEvents) / sizeof(EventTypeSpec), myAccessibilityEvents,
this, &m_plistAccessibilityEventHandlerRef);
} else {
@ -1250,22 +1247,33 @@ pascal OSStatus BOINCListAccessibilityEventHandler( EventHandlerCallRef inHandle
}
pascal OSStatus AttachListAccessibilityEventHandler( EventHandlerCallRef inHandlerCallRef,
pascal OSStatus HTMLListAccessibilityEventHandler( EventHandlerCallRef inHandlerCallRef,
EventRef inEvent, void* pData) {
const UInt32 eventClass = GetEventClass(inEvent);
const UInt32 eventKind = GetEventKind(inEvent);
CProjectListCtrlAccessible* pProjectListCtrlAccessible = NULL;
CProjectListCtrl* pProjectListCtrl = NULL;
CNoticeListCtrlAccessible* pNoticeListCtrlAccessible = NULL;
CNoticeListCtrl* pNoticeListCtrl = NULL;
OSStatus err;
CProjectListCtrlAccessible* pAccessible = (CProjectListCtrlAccessible*)pData;
if (pAccessible == NULL) {
return eventNotHandledErr;
pProjectListCtrlAccessible = wxDynamicCast(pData, CProjectListCtrlAccessible);
if (pProjectListCtrlAccessible != NULL) {
pProjectListCtrl = wxDynamicCast(pProjectListCtrlAccessible->GetWindow(), CProjectListCtrl);
if (pProjectListCtrl == NULL) {
return eventNotHandledErr;
}
} else {
pNoticeListCtrlAccessible = wxDynamicCast(pData, CNoticeListCtrlAccessible);
if (pNoticeListCtrlAccessible == NULL) {
return eventNotHandledErr;
}
pNoticeListCtrl = wxDynamicCast(pNoticeListCtrlAccessible->GetWindow(), CNoticeListCtrl);
if (pNoticeListCtrl == NULL) {
return eventNotHandledErr;
}
}
CProjectListCtrl* pCtrl = wxDynamicCast(pAccessible->GetWindow(), CProjectListCtrl);
if (pCtrl == NULL) {
return eventNotHandledErr;
}
if (eventClass != kEventClassAccessibility) {
return eventNotHandledErr;
}
@ -1303,9 +1311,13 @@ pascal OSStatus AttachListAccessibilityEventHandler( EventHandlerCallRef inHandl
if (err) return err;
wxPoint p((int)where.x, (int)where.y);
pCtrl->ScreenToClient(&p.x, &p.y);
err = pAccessible->HitTest(p, &hitRow, NULL);
if (pProjectListCtrlAccessible) {
pProjectListCtrl->ScreenToClient(&p.x, &p.y);
err = pProjectListCtrlAccessible->HitTest(p, &hitRow, NULL);
} else {
pNoticeListCtrl->ScreenToClient(&p.x, &p.y);
err = pNoticeListCtrlAccessible->HitTest(p, &hitRow, NULL);
}
if (err) {
return eventNotHandledErr;
@ -1406,7 +1418,11 @@ pascal OSStatus AttachListAccessibilityEventHandler( EventHandlerCallRef inHandl
wxRect r;
HISize theSize;
err = pAccessible->GetLocation(r, row);
if (pProjectListCtrlAccessible) {
err = pProjectListCtrlAccessible->GetLocation(r, row);
} else {
err = pNoticeListCtrlAccessible->GetLocation(r, row);
}
if (err) {
return eventNotHandledErr;
}
@ -1420,20 +1436,18 @@ pascal OSStatus AttachListAccessibilityEventHandler( EventHandlerCallRef inHandl
} else if ( CFStringCompare( attribute, kAXPositionAttribute, 0 ) == kCFCompareEqualTo ) {
wxRect r;
HIPoint pt;
int x, y;
err = pAccessible->GetLocation(r, row);
if (pProjectListCtrlAccessible) {
err = pProjectListCtrlAccessible->GetLocation(r, row);
} else {
err = pNoticeListCtrlAccessible->GetLocation(r, row);
}
if (err) {
return eventNotHandledErr;
}
x = r.x;
y = r.y;
// Now convert to global coordinates
pCtrl->ClientToScreen(&x, &y);
pt.x = x;
pt.y = y;
pt.x = r.x;
pt.y = r.y;
SetEventParameter(inEvent, kEventParamAccessibleAttributeValue, typeHIPoint, sizeof(HIPoint), &pt);
return noErr;
@ -1449,7 +1463,11 @@ pascal OSStatus AttachListAccessibilityEventHandler( EventHandlerCallRef inHandl
AXUIElementRef child;
int i, n;
err = pAccessible->GetChildCount(&n);
if (pProjectListCtrlAccessible) {
err = pProjectListCtrlAccessible->GetChildCount(&n);
} else {
err = pNoticeListCtrlAccessible->GetChildCount(&n);
}
children = CFArrayCreateMutable( kCFAllocatorDefault, n, &kCFTypeArrayCallBacks );
for ( i = 0; i < n; i++ ) {
@ -1486,7 +1504,11 @@ pascal OSStatus AttachListAccessibilityEventHandler( EventHandlerCallRef inHandl
AXUIElementRef parent;
HIViewRef parentView;
parentView = HIViewGetSuperview(pAccessible->m_listView);
if (pProjectListCtrlAccessible) {
parentView = HIViewGetSuperview(pProjectListCtrlAccessible->m_listView);
} else {
parentView = HIViewGetSuperview(pNoticeListCtrlAccessible->m_listView);
}
parent = AXUIElementCreateWithHIObjectAndIdentifier((HIObjectRef)parentView, 0);
if (parent == NULL) {
return eventNotHandledErr;
@ -1505,19 +1527,34 @@ pascal OSStatus AttachListAccessibilityEventHandler( EventHandlerCallRef inHandl
if ( CFStringCompare( attribute, kAXDescriptionAttribute, 0 ) == kCFCompareEqualTo ) {
wxString str, buf;
int n;
Boolean selected = false;
err = pAccessible->GetChildCount(&n);
if (pProjectListCtrlAccessible) {
err = pProjectListCtrlAccessible->GetChildCount(&n);
} else {
err = pNoticeListCtrlAccessible->GetChildCount(&n);
}
if (err) {
return eventNotHandledErr;
}
if (pCtrl->IsSelected(row - 1)) {
if (pProjectListCtrl) {
selected = pProjectListCtrl->IsSelected(row - 1);
} else {
selected = pNoticeListCtrl->IsSelected(row - 1);
}
if (selected) {
str.Printf(_("selected row %d of %d; "), row, n);
} else {
str.Printf(_("row %d of %d; "), row, n);
}
err = pAccessible->GetDescription(row, &buf);
if (pProjectListCtrlAccessible) {
err = pProjectListCtrlAccessible->GetDescription(row, &buf);
} else {
err = pNoticeListCtrlAccessible->GetDescription(row, &buf);
}
if (err) {
return eventNotHandledErr;
}
@ -1532,7 +1569,11 @@ pascal OSStatus AttachListAccessibilityEventHandler( EventHandlerCallRef inHandl
AXUIElementRef parent;
HIViewRef parentView;
parentView = pAccessible->m_listView;
if (pProjectListCtrlAccessible) {
parentView = pProjectListCtrlAccessible->m_listView;
} else {
parentView = pNoticeListCtrlAccessible->m_listView;
}
parent = AXUIElementCreateWithHIObjectAndIdentifier((HIObjectRef)parentView, 0);
if (parent == NULL) {
return eventNotHandledErr;
@ -1600,7 +1641,11 @@ pascal OSStatus AttachListAccessibilityEventHandler( EventHandlerCallRef inHandl
wxString str;
wxListItem headerItem;
pAccessible->GetName(row, &str);
if (pProjectListCtrlAccessible) {
pProjectListCtrlAccessible->GetName(row, &str);
} else {
pNoticeListCtrlAccessible->GetName(row, &str);
}
CFStringRef title = CFStringCreateWithCString(NULL, str.char_str(), kCFStringEncodingUTF8);
SetEventParameter( inEvent, kEventParamAccessibleAttributeValue, typeCFTypeRef, sizeof( title ), &title );
@ -1705,479 +1750,11 @@ pascal OSStatus AttachListAccessibilityEventHandler( EventHandlerCallRef inHandl
if ( CFStringCompare( action, kAXPressAction, 0 ) != kCFCompareEqualTo ) {
return eventNotHandledErr;
}
err = pAccessible->DoDefaultAction(inIdentifier);
if (err) {
return eventNotHandledErr;
}
return noErr;
}
break;
default:
return eventNotHandledErr;
} // End switch(eventKind)
return eventNotHandledErr;
}
pascal OSStatus NoticeListAccessibilityEventHandler( EventHandlerCallRef inHandlerCallRef,
EventRef inEvent, void* pData) {
const UInt32 eventClass = GetEventClass(inEvent);
const UInt32 eventKind = GetEventKind(inEvent);
OSStatus err;
CProjectListCtrlAccessible* pAccessible = (CProjectListCtrlAccessible*)pData;
if (pAccessible == NULL) {
return eventNotHandledErr;
}
CNoticeListCtrl* pCtrl = wxDynamicCast(pAccessible->GetWindow(), CNoticeListCtrl);
if (pCtrl == NULL) {
return eventNotHandledErr;
}
if (eventClass != kEventClassAccessibility) {
return eventNotHandledErr;
}
AXUIElementRef element;
UInt64 inIdentifier = 0;
UInt64 outIdentifier = 0;
SInt32 row = 0;
HIObjectRef obj = NULL;
err = GetEventParameter (inEvent, kEventParamAccessibleObject,
typeCFTypeRef, NULL, sizeof(typeCFTypeRef), NULL, &element);
if (err) return err;
AXUIElementGetIdentifier( element, &inIdentifier );
obj = AXUIElementGetHIObject(element);
row = inIdentifier;
switch (eventKind) {
#pragma mark kEventAccessibleGetChildAtPoint
case kEventAccessibleGetChildAtPoint:
{
CFTypeRef child = NULL;
HIPoint where;
int hitRow;
// Only the whole view can be tested since the parts don't have sub-parts.
if (inIdentifier != 0) {
return noErr;
}
err = GetEventParameter (inEvent, kEventParamMouseLocation,
typeHIPoint, NULL, sizeof(HIPoint), NULL, &where);
if (err) return err;
wxPoint p((int)where.x, (int)where.y);
pCtrl->ScreenToClient(&p.x, &p.y);
err = pAccessible->HitTest(p, &hitRow, NULL);
if (err) {
return eventNotHandledErr;
}
if (hitRow >= 0) {
outIdentifier = hitRow + 1;
child = AXUIElementCreateWithHIObjectAndIdentifier(obj, outIdentifier );
if (child == NULL) {
return eventNotHandledErr;
}
err = SetEventParameter (inEvent, kEventParamAccessibleChild, typeCFTypeRef,
sizeof(typeCFTypeRef), &child);
if (err) {
return eventNotHandledErr;
}
}
return noErr;
}
break;
#pragma mark kEventAccessibleGetFocusedChild
case kEventAccessibleGetFocusedChild:
return noErr;
break;
#pragma mark kEventAccessibleGetAllAttributeNames
case kEventAccessibleGetAllAttributeNames:
{
CFMutableArrayRef namesArray;
err = GetEventParameter (inEvent, kEventParamAccessibleAttributeNames,
typeCFMutableArrayRef, NULL, sizeof(typeCFMutableArrayRef), NULL, &namesArray);
if (err)
return err;
CallNextEventHandler( inHandlerCallRef, inEvent );
if ( inIdentifier == 0 )
{
// Identifier 0 means "the whole view".
// Let accessibility know that this view has children and can
// return a list of them.
CFArrayAppendValue( namesArray, kAXChildrenAttribute );
if (pProjectListCtrlAccessible) {
err = pProjectListCtrlAccessible->DoDefaultAction(inIdentifier);
} else {
// Let accessibility know that this view's children can return description,
// size, position, parent window, top level element and isFocused attributes.
CFArrayAppendValue( namesArray, kAXWindowAttribute );
CFArrayAppendValue( namesArray, kAXTopLevelUIElementAttribute );
CFArrayAppendValue( namesArray, kAXDescriptionAttribute );
CFArrayAppendValue( namesArray, kAXSizeAttribute );
CFArrayAppendValue( namesArray, kAXPositionAttribute );
CFArrayAppendValue( namesArray, kAXTitleAttribute );
CFArrayAppendValue( namesArray, kAXEnabledAttribute );
err = pNoticeListCtrlAccessible->DoDefaultAction(inIdentifier);
}
CFArrayAppendValue( namesArray, kAXFocusedAttribute );
CFArrayAppendValue( namesArray, kAXRoleAttribute );
CFArrayAppendValue( namesArray, kAXRoleDescriptionAttribute );
CFArrayAppendValue( namesArray, kAXParentAttribute );
return noErr;
}
break;
#pragma mark kEventAccessibleGetAllParameterizedAttributeNames
case kEventAccessibleGetAllParameterizedAttributeNames:
{
CFMutableArrayRef namesArray;
err = GetEventParameter (inEvent, kEventParamAccessibleAttributeNames,
typeCFMutableArrayRef, NULL, sizeof(typeCFMutableArrayRef), NULL, &namesArray);
if (err) return err;
return noErr;
}
break;
#pragma mark kEventAccessibleGetNamedAttribute
case kEventAccessibleGetNamedAttribute:
{
CFStringRef attribute;
err = GetEventParameter (inEvent, kEventParamAccessibleAttributeName,
typeCFStringRef, NULL, sizeof(typeCFStringRef), NULL, &attribute);
if (err) return err;
if ( CFStringCompare( attribute, kAXFocusedAttribute, 0 ) == kCFCompareEqualTo ) {
// Return whether or not this part is focused.
//TODO: Add kAXFocusedAttribute support?
Boolean focused = false;
SetEventParameter( inEvent, kEventParamAccessibleAttributeValue, typeBoolean, sizeof( focused ), &focused );
return noErr;
} else if ( CFStringCompare( attribute, kAXSizeAttribute, 0 ) == kCFCompareEqualTo ) {
wxRect r;
HISize theSize;
err = pAccessible->GetLocation(r, row);
if (err) {
return eventNotHandledErr;
}
theSize.width = r.width;
theSize.height = r.height;
SetEventParameter( inEvent, kEventParamAccessibleAttributeValue, typeHISize, sizeof( HISize ), &theSize );
return noErr;
} else if ( CFStringCompare( attribute, kAXPositionAttribute, 0 ) == kCFCompareEqualTo ) {
wxRect r;
HIPoint pt;
int x, y;
err = pAccessible->GetLocation(r, row);
if (err) {
return eventNotHandledErr;
}
x = r.x;
y = r.y;
// Now convert to global coordinates
// pCtrl->ClientToScreen(&x, &y);
pt.x = x;
pt.y = y;
SetEventParameter(inEvent, kEventParamAccessibleAttributeValue, typeHIPoint, sizeof(HIPoint), &pt);
return noErr;
}
if ( inIdentifier == 0 ) {
// String compare the incoming attribute name and return the appropriate accessibility
// information as an event parameter.
if ( CFStringCompare( attribute, kAXChildrenAttribute, 0 ) == kCFCompareEqualTo ) {
// Create and return an array of AXUIElements describing the children of this view.
CFMutableArrayRef children;
AXUIElementRef child;
int i, n;
err = pAccessible->GetChildCount(&n);
children = CFArrayCreateMutable( kCFAllocatorDefault, n, &kCFTypeArrayCallBacks );
for ( i = 0; i < n; i++ ) {
outIdentifier = i+1;
child = AXUIElementCreateWithHIObjectAndIdentifier( obj, outIdentifier );
CFArrayAppendValue( children, child );
CFRelease( child );
}
SetEventParameter( inEvent, kEventParamAccessibleAttributeValue, typeCFTypeRef, sizeof( children ), &children );
CFRelease( children );
return noErr;
} else if ( CFStringCompare( attribute, kAXRoleAttribute, 0 ) == kCFCompareEqualTo ) {
// Return a string indicating the role of this view. Using the table role doesn't work.
CFStringRef role = kAXListRole;
SetEventParameter( inEvent, kEventParamAccessibleAttributeValue, typeCFTypeRef, sizeof( role ), &role );
return noErr;
} else if ( CFStringCompare( attribute, kAXRoleDescriptionAttribute, 0 ) == kCFCompareEqualTo ) {
// Return a string indicating the role of this part.
//TODO: specify whether projects or account managers
wxString str;
str = _("list of projects or account managers");
CFStringRef roleDesc = CFStringCreateWithCString(NULL, str.char_str(), kCFStringEncodingUTF8);
SetEventParameter( inEvent, kEventParamAccessibleAttributeValue, typeCFTypeRef, sizeof( roleDesc ), &roleDesc );
CFRelease( roleDesc );
return noErr;
} else if ( CFStringCompare( attribute, kAXParentAttribute, 0 ) == kCFCompareEqualTo ) {
AXUIElementRef parent;
HIViewRef parentView;
parentView = HIViewGetSuperview(pAccessible->m_listView);
parent = AXUIElementCreateWithHIObjectAndIdentifier((HIObjectRef)parentView, 0);
if (parent == NULL) {
return eventNotHandledErr;
}
SetEventParameter( inEvent, kEventParamAccessibleAttributeValue, typeCFTypeRef, sizeof( parent ), &parent );
CFRelease( parent );
return noErr;
} else {
return CallNextEventHandler( inHandlerCallRef, inEvent );
}
} else { // End if ( inIdentifier == 0 )
if ( CFStringCompare( attribute, kAXDescriptionAttribute, 0 ) == kCFCompareEqualTo ) {
wxString str, buf;
int n;
err = pAccessible->GetChildCount(&n);
if (err) {
return eventNotHandledErr;
}
if (pCtrl->IsSelected(row - 1)) {
str.Printf(_("selected row %d of %d; "), row, n);
} else {
str.Printf(_("row %d of %d; "), row, n);
}
err = pAccessible->GetDescription(row, &buf);
if (err) {
return eventNotHandledErr;
}
str += buf;
CFStringRef description = CFStringCreateWithCString(NULL, str.char_str(), kCFStringEncodingUTF8);
SetEventParameter( inEvent, kEventParamAccessibleAttributeValue, typeCFTypeRef, sizeof( description ), &description );
CFRelease( description );
return noErr;
} else if ( CFStringCompare( attribute, kAXParentAttribute, 0 ) == kCFCompareEqualTo ) {
AXUIElementRef parent;
HIViewRef parentView;
parentView = pAccessible->m_listView;
parent = AXUIElementCreateWithHIObjectAndIdentifier((HIObjectRef)parentView, 0);
if (parent == NULL) {
return eventNotHandledErr;
}
SetEventParameter( inEvent, kEventParamAccessibleAttributeValue, typeCFTypeRef, sizeof( parent ), &parent );
CFRelease( parent );
return noErr;
} else if ( CFStringCompare( attribute, kAXSubroleAttribute, 0 ) == kCFCompareEqualTo ) {
return eventNotHandledErr;
} else if ( CFStringCompare( attribute, kAXRoleAttribute, 0 ) == kCFCompareEqualTo ) {
// Return a string indicating the role of this part. The parts of the view behave like
// buttons, so use that system role.
CFStringRef role = kAXStaticTextRole; // kAXRowRole;
SetEventParameter( inEvent, kEventParamAccessibleAttributeValue, typeCFTypeRef, sizeof( role ), &role );
return noErr;
} else if ( CFStringCompare( attribute, kAXRoleDescriptionAttribute, 0 ) == kCFCompareEqualTo ) {
// Return a string describing the role of this part. Use the system description.
CFStringRef roleDesc = HICopyAccessibilityRoleDescription( kAXRowRole, NULL );
SetEventParameter( inEvent, kEventParamAccessibleAttributeValue, typeCFTypeRef, sizeof( roleDesc ), &roleDesc );
CFRelease( roleDesc );
return noErr;
} else if ( CFStringCompare( attribute, kAXWindowAttribute, 0 ) == kCFCompareEqualTo
|| CFStringCompare( attribute, kAXTopLevelUIElementAttribute, 0 ) == kCFCompareEqualTo ) {
// Return the window or top level ui element for this part. They are both the same so re-use the code.
AXUIElementRef windOrTopUI;
WindowRef win = GetControlOwner((HIViewRef)obj);
if (win == NULL) {
return eventNotHandledErr;
}
windOrTopUI = AXUIElementCreateWithHIObjectAndIdentifier( (HIObjectRef)win, 0 );
if (windOrTopUI == NULL) {
return eventNotHandledErr;
}
SetEventParameter( inEvent, kEventParamAccessibleAttributeValue, typeCFTypeRef, sizeof( windOrTopUI ), &windOrTopUI );
CFRelease( windOrTopUI );
return noErr;
} else if ( CFStringCompare( attribute, kAXEnabledAttribute, 0 ) == kCFCompareEqualTo ) {
Boolean enabled = true;
SetEventParameter( inEvent, kEventParamAccessibleAttributeValue, typeBoolean, sizeof( enabled ), &enabled );
return noErr;
//TODO: Add kAXFocusedAttribute support?
#if 0
} else if ( CFStringCompare( attribute, kAXFocusedAttribute, 0 ) == kCFCompareEqualTo ) {
// Return whether or not this part is focused.
Boolean focused = false;
SetEventParameter( inEvent, kEventParamAccessibleAttributeValue, typeBoolean, sizeof( focused ), &focused );
return noErr;
#endif
} else if ( CFStringCompare( attribute, kAXTitleAttribute, 0 ) == kCFCompareEqualTo ) {
// Return the item's text
wxString str;
wxListItem headerItem;
pAccessible->GetName(row, &str);
CFStringRef title = CFStringCreateWithCString(NULL, str.char_str(), kCFStringEncodingUTF8);
SetEventParameter( inEvent, kEventParamAccessibleAttributeValue, typeCFTypeRef, sizeof( title ), &title );
CFRelease( title );
return noErr;
} else {
return eventNotHandledErr;
}
} // End if ( inIdentifier != 0 )
break;
} // End case kEventAccessibleGetNamedAttribute:
#pragma mark kEventAccessibleIsNamedAttributeSettable
case kEventAccessibleIsNamedAttributeSettable:
{
CFStringRef attribute;
Boolean isSettable = false;
err = GetEventParameter (inEvent, kEventParamAccessibleAttributeName,
typeCFStringRef, NULL, sizeof(typeCFStringRef), NULL, &attribute);
if (err) return err;
// The focused attribute is the only settable attribute for this view,
// and it can only be set on part (or subelements), not the whole view.
if (inIdentifier != 0)
{
if ( CFStringCompare( attribute, kAXFocusedAttribute, 0 ) == kCFCompareEqualTo )
{
isSettable = true;
}
}
SetEventParameter( inEvent, kEventParamAccessibleAttributeSettable, typeBoolean, sizeof( Boolean ), &isSettable );
return noErr;
}
break;
#pragma mark kEventAccessibleSetNamedAttribute
case kEventAccessibleSetNamedAttribute:
{
return eventNotHandledErr;
}
break;
#pragma mark kEventAccessibleGetAllActionNames
case kEventAccessibleGetAllActionNames:
{
CFMutableArrayRef array;
err = GetEventParameter (inEvent, kEventParamAccessibleActionNames,
typeCFMutableArrayRef, NULL, sizeof(typeCFMutableArrayRef), NULL, &array);
if (err) return err;
if (inIdentifier != 0) {
CFArrayAppendValue( array, kAXPressAction );
}
return noErr;
}
break;
#pragma mark kEventAccessibleGetNamedActionDescription
case kEventAccessibleGetNamedActionDescription:
{
CFStringRef action;
CFMutableStringRef desc;
CFStringRef selfDesc = NULL;
if (inIdentifier == 0) {
return eventNotHandledErr;
}
err = GetEventParameter (inEvent, kEventParamAccessibleActionName,
typeCFStringRef, NULL, sizeof(typeCFStringRef), NULL, &action);
if (err) return err;
err = GetEventParameter (inEvent, kEventParamAccessibleActionDescription,
typeCFMutableStringRef, NULL, sizeof(typeCFMutableStringRef), NULL, &desc);
if (err) return err;
selfDesc = HICopyAccessibilityActionDescription( action );
CFStringReplaceAll( desc, selfDesc );
CFRelease( selfDesc );
return noErr;
}
break;
#pragma mark kEventAccessiblePerformNamedAction
case kEventAccessiblePerformNamedAction:
{
CFStringRef action;
if (inIdentifier == 0) {
return eventNotHandledErr;
}
err = GetEventParameter (inEvent, kEventParamAccessibleActionName,
typeCFStringRef, NULL, sizeof(typeCFStringRef), NULL, &action);
if (err) return err;
if ( CFStringCompare( action, kAXPressAction, 0 ) != kCFCompareEqualTo ) {
return eventNotHandledErr;
}
err = pAccessible->DoDefaultAction(inIdentifier);
if (err) {
return eventNotHandledErr;
}
@ -2194,6 +1771,7 @@ pascal OSStatus NoticeListAccessibilityEventHandler( EventHandlerCallRef inHandl
}
pascal OSStatus SimpleAccessibilityEventHandler( EventHandlerCallRef inHandlerCallRef,
EventRef inEvent, void* pData) {
const UInt32 eventClass = GetEventClass(inEvent);