MGR: Implement Mac accessibility for Event Log

svn path=/trunk/boinc/; revision=20227
This commit is contained in:
Charlie Fenton 2010-01-21 12:47:09 +00:00
parent bdd4621f7a
commit ebf83cdd54
6 changed files with 161 additions and 33 deletions

View File

@ -586,3 +586,12 @@ David 19 Jan 2010
work_fetch.cpp,h
html/user/
language_select.php
Charlie 21 Jan 2010
- MGR: Implement Mac accessibility for Event Log.
clientgui/
BOINCListCtrl.h
DlgEventLogListCtrl.cpp, .h
mac/
MacAccessiblity.cpp, .h

View File

@ -42,6 +42,10 @@
#include "wx/generic/listctrl.h"
#endif
#ifdef __WXMAC__
#include "macAccessiblity.h"
#endif
class CBOINCBaseView;
class CDrawProgressBarEvent;
@ -94,11 +98,9 @@ private:
#ifdef __WXMAC__
void SetupMacAccessibilitySupport();
void RemoveMacAccessibilitySupport();
CBOINCBaseView* GetParentView() { return m_pParentView; }
HIViewRef m_headerView;
HIViewRef m_bodyView;
struct ListAccessData accessibilityHandlerData;
EventHandlerRef m_pHeaderAccessibilityEventHandlerRef;
EventHandlerRef m_pBodyAccessibilityEventHandlerRef;
#endif

View File

@ -33,20 +33,32 @@
#include "DlgEventLog.h"
IMPLEMENT_DYNAMIC_CLASS(CDlgEventLogListCtrl, wxListView)
IMPLEMENT_DYNAMIC_CLASS(CDlgEventLogListCtrl, LISTCTRL_BASE)
CDlgEventLogListCtrl::CDlgEventLogListCtrl() {}
CDlgEventLogListCtrl::CDlgEventLogListCtrl(CDlgEventLog* pView, wxWindowID iListWindowID, wxInt32 iListWindowFlags)
:wxListView(pView, iListWindowID, wxDefaultPosition, wxSize(640,480), iListWindowFlags)
: LISTCTRL_BASE(pView, iListWindowID, wxDefaultPosition, wxSize(640,480), iListWindowFlags)
{
m_pParentView = pView;
m_bIsSingleSelection = (iListWindowFlags & wxLC_SINGLE_SEL) ? true : false ;
#ifdef __WXMAC__
SetupMacAccessibilitySupport();
#endif
}
#ifdef __WXMAC__
CDlgEventLogListCtrl::~CDlgEventLogListCtrl()
{
RemoveMacAccessibilitySupport();
}
#endif
wxString CDlgEventLogListCtrl::OnGetItemText(long item, long column) const {
wxASSERT(m_pParentView);
wxASSERT(wxDynamicCast(m_pParentView, CDlgEventLog));

View File

@ -22,17 +22,29 @@
#pragma interface "DlgEventLogListCtrl.cpp"
#endif
#ifdef __WXMAC__
#include "macAccessiblity.h"
#define LISTCTRL_BASE wxGenericListCtrl
#else
#define LISTCTRL_BASE wxListView
#endif
#define DEFAULT_LIST_MULTI_SEL_FLAGS wxLC_REPORT | wxLC_VIRTUAL
class CDlgEventLog;
class CDlgEventLogListCtrl : public wxListView {
class CDlgEventLogListCtrl : public LISTCTRL_BASE
{
DECLARE_DYNAMIC_CLASS(CDlgEventLogListCtrl)
public:
CDlgEventLogListCtrl();
CDlgEventLogListCtrl(CDlgEventLog* pView, wxWindowID iListWindowID, int iListWindowFlags);
#ifdef __WXMAC__
~CDlgEventLogListCtrl();
#endif
private:
virtual wxString OnGetItemText(long item, long column) const;
@ -43,6 +55,16 @@ private:
bool m_bIsSingleSelection;
CDlgEventLog* m_pParentView;
#ifdef __WXMAC__
void SetupMacAccessibilitySupport();
void RemoveMacAccessibilitySupport();
struct ListAccessData accessibilityHandlerData;
EventHandlerRef m_pHeaderAccessibilityEventHandlerRef;
EventHandlerRef m_pBodyAccessibilityEventHandlerRef;
#endif
};
#endif

View File

@ -23,9 +23,11 @@
#include "BOINCGUIApp.h"
#include "BOINCBaseFrame.h"
#include "BOINCBaseView.h"
#include "DlgEventLog.h"
#include "MainDocument.h"
#include "AdvancedFrame.h"
#include "BOINCListCtrl.h"
#include "DlgEventLogListCtrl.h"
#include "ProjectListCtrl.h"
#include "ViewStatistics.h"
#include "wxPieCtrl.h"
@ -98,20 +100,29 @@ pascal OSStatus PieCtrlAccessibilityEventHandler( EventHandlerCallRef inHandlerC
void CBOINCListCtrl::SetupMacAccessibilitySupport() {
#if !USE_NATIVE_LISTCONTROL
HIViewRef listControlView;
OSErr err;
HIViewRef listControlView;
HIViewRef headerView;
HIViewRef bodyView;
OSErr err;
listControlView = (HIViewRef)GetHandle();
m_headerView = HIViewGetFirstSubview(listControlView);
m_bodyView = HIViewGetNextView(m_headerView);
err = HIViewSetEnabled(m_headerView, true);
err = InstallHIObjectEventHandler((HIObjectRef)m_headerView, NewEventHandlerUPP(BOINCListHeaderAccessibilityEventHandler),
headerView = HIViewGetFirstSubview(listControlView);
bodyView = HIViewGetNextView(headerView);
err = HIViewSetEnabled(headerView, true);
accessibilityHandlerData.pList = (wxGenericListCtrl*)this;
accessibilityHandlerData.pView = m_pParentView;
accessibilityHandlerData.headerView = headerView;
accessibilityHandlerData.bodyView = bodyView;
accessibilityHandlerData.pEventLog = NULL;
err = InstallHIObjectEventHandler((HIObjectRef)headerView, NewEventHandlerUPP(BOINCListHeaderAccessibilityEventHandler),
sizeof(myAccessibilityEvents) / sizeof(EventTypeSpec), myAccessibilityEvents,
this, &m_pHeaderAccessibilityEventHandlerRef);
&accessibilityHandlerData, &m_pHeaderAccessibilityEventHandlerRef);
err = InstallHIObjectEventHandler((HIObjectRef)m_bodyView, NewEventHandlerUPP(BOINCListBodyAccessibilityEventHandler),
err = InstallHIObjectEventHandler((HIObjectRef)bodyView, NewEventHandlerUPP(BOINCListBodyAccessibilityEventHandler),
sizeof(myAccessibilityEvents) / sizeof(EventTypeSpec), myAccessibilityEvents,
this, &m_pBodyAccessibilityEventHandlerRef);
&accessibilityHandlerData, &m_pBodyAccessibilityEventHandlerRef);
#endif
}
@ -124,6 +135,43 @@ void CBOINCListCtrl::RemoveMacAccessibilitySupport() {
}
void CDlgEventLogListCtrl::SetupMacAccessibilitySupport() {
#if !USE_NATIVE_LISTCONTROL
HIViewRef listControlView;
HIViewRef headerView;
HIViewRef bodyView;
OSErr err;
listControlView = (HIViewRef)GetHandle();
headerView = HIViewGetFirstSubview(listControlView);
bodyView = HIViewGetNextView(headerView);
err = HIViewSetEnabled(headerView, true);
accessibilityHandlerData.pList = (wxGenericListCtrl*)this;
accessibilityHandlerData.pView = NULL;
accessibilityHandlerData.headerView = headerView;
accessibilityHandlerData.bodyView = bodyView;
accessibilityHandlerData.pEventLog = m_pParentView;
err = InstallHIObjectEventHandler((HIObjectRef)headerView, NewEventHandlerUPP(BOINCListHeaderAccessibilityEventHandler),
sizeof(myAccessibilityEvents) / sizeof(EventTypeSpec), myAccessibilityEvents,
&accessibilityHandlerData, &m_pHeaderAccessibilityEventHandlerRef);
err = InstallHIObjectEventHandler((HIObjectRef)bodyView, NewEventHandlerUPP(BOINCListBodyAccessibilityEventHandler),
sizeof(myAccessibilityEvents) / sizeof(EventTypeSpec), myAccessibilityEvents,
&accessibilityHandlerData, &m_pBodyAccessibilityEventHandlerRef);
#endif
}
void CDlgEventLogListCtrl::RemoveMacAccessibilitySupport() {
#if !USE_NATIVE_LISTCONTROL
::RemoveEventHandler(m_pHeaderAccessibilityEventHandlerRef);
::RemoveEventHandler(m_pBodyAccessibilityEventHandlerRef);
#endif
}
void CProjectListCtrlAccessible::SetupMacAccessibilitySupport() {
OSErr err;
@ -242,7 +290,11 @@ OSStatus BOINCListAccessibilityEventHandler( EventHandlerCallRef inHandlerCallRe
const UInt32 eventClass = GetEventClass(inEvent);
const UInt32 eventKind = GetEventKind(inEvent);
OSStatus err;
CBOINCListCtrl* pList = (CBOINCListCtrl*)pData;
wxGenericListCtrl* pList = ((struct ListAccessData*)pData)->pList;
CBOINCBaseView* pView = ((struct ListAccessData*)pData)->pView;
HIViewRef headerView = ((struct ListAccessData*)pData)->headerView;
HIViewRef bodyView = ((struct ListAccessData*)pData)->bodyView;
CDlgEventLog* pEventLog = ((struct ListAccessData*)pData)->pEventLog;
if (eventClass != kEventClassAccessibility) {
return eventNotHandledErr;
@ -253,7 +305,6 @@ OSStatus BOINCListAccessibilityEventHandler( EventHandlerCallRef inHandlerCallRe
UInt64 outIdentifier = 0;
SInt32 row = 0;
SInt32 col = 0;
CBOINCBaseView* pView = NULL;
HIObjectRef obj = NULL;
err = GetEventParameter (inEvent, kEventParamAccessibleObject,
@ -262,8 +313,6 @@ OSStatus BOINCListAccessibilityEventHandler( EventHandlerCallRef inHandlerCallRe
AXUIElementGetIdentifier( element, &inIdentifier );
obj = AXUIElementGetHIObject(element);
pView = pList->GetParentView();
if (inIdentifier) {
if (! isHeader) {
@ -305,7 +354,7 @@ OSStatus BOINCListAccessibilityEventHandler( EventHandlerCallRef inHandlerCallRe
}
if (isHeader) {
if ((p.y > 0) || (p.y < -pList->GetHeaderHeight())) {
if ((p.y > 0) || (p.y < -pList->m_headerHeight)) {
return noErr;
}
outIdentifier = col+1;
@ -469,7 +518,13 @@ OSStatus BOINCListAccessibilityEventHandler( EventHandlerCallRef inHandlerCallRe
str = _("blank");
} else {
str = _("list of ");
str += pView->GetViewDisplayName();
if (pEventLog) {
str += _("events");
} else {
if (pView) {
str += pView->GetViewDisplayName();
}
}
if (pList->GetItemCount() <= 0) {
str += _(" is empty");
}
@ -484,7 +539,7 @@ OSStatus BOINCListAccessibilityEventHandler( EventHandlerCallRef inHandlerCallRe
AXUIElementRef parent;
HIViewRef parentView;
parentView = HIViewGetSuperview(isHeader ? pList->m_headerView : pList->m_bodyView);
parentView = HIViewGetSuperview(isHeader ? headerView : bodyView);
parent = AXUIElementCreateWithHIObjectAndIdentifier((HIObjectRef)parentView, 0);
if (parent == NULL) {
return eventNotHandledErr;
@ -496,7 +551,7 @@ OSStatus BOINCListAccessibilityEventHandler( EventHandlerCallRef inHandlerCallRe
} else if ( CFStringCompare( attribute, kAXSizeAttribute, 0 ) == kCFCompareEqualTo ) {
HIRect r;
err = HIViewGetBounds(isHeader ? pList->m_headerView : pList->m_bodyView, &r);
err = HIViewGetBounds(isHeader ? headerView : bodyView, &r);
HISize size = r.size;
SetEventParameter( inEvent, kEventParamAccessibleAttributeValue, typeHISize, sizeof( HISize ), &size );
@ -506,14 +561,14 @@ OSStatus BOINCListAccessibilityEventHandler( EventHandlerCallRef inHandlerCallRe
HIRect r;
HIPoint pt;
err = HIViewGetBounds(isHeader ? pList->m_headerView : pList->m_bodyView, &r);
err = HIViewGetBounds(isHeader ? headerView : bodyView, &r);
int x = r.origin.x, y = r.origin.y;
// Now convert to global coordinates
pList->ClientToScreen(&x, &y);
pt.x = x;
if (isHeader) {
pt.y = y - pList->GetHeaderHeight();
pt.y = y - pList->m_headerHeight;
} else {
pt.y = y;
}
@ -531,6 +586,7 @@ OSStatus BOINCListAccessibilityEventHandler( EventHandlerCallRef inHandlerCallRe
if ( CFStringCompare( attribute, kAXDescriptionAttribute, 0 ) == kCFCompareEqualTo ) {
wxString str, buf;
int rowCount;
Boolean isCurrentSortCol = false;
if (isHeader) {
wxListItem headerItem;
@ -542,7 +598,12 @@ OSStatus BOINCListAccessibilityEventHandler( EventHandlerCallRef inHandlerCallRe
pList->GetColumn(col, headerItem);
buf.Printf(_("%d of %d; "), col+1, pList->GetColumnCount());
if (col == pView->m_iSortColumn) {
if (pView) {
if (col == pView->m_iSortColumn) {
isCurrentSortCol = true;
}
}
if (isCurrentSortCol) {
str = _("current sort column ");
str += buf;
str += (pView->m_bReverseSort ? _(" descending order ") : _(" ascending order "));
@ -570,7 +631,11 @@ OSStatus BOINCListAccessibilityEventHandler( EventHandlerCallRef inHandlerCallRe
}
buf.Printf(_("column %d; "), col+1);
str += buf;
buf = pView->FireOnListGetItemText(row, col);
if (pEventLog) {
buf = pEventLog->OnListGetItemText(row, col);
} else {
buf = pView->FireOnListGetItemText(row, col);
}
if (buf.IsEmpty()) {
buf = _("blank");
}
@ -586,7 +651,7 @@ OSStatus BOINCListAccessibilityEventHandler( EventHandlerCallRef inHandlerCallRe
AXUIElementRef parent;
HIViewRef parentView;
parentView = isHeader ? pList->m_headerView : pList->m_bodyView;
parentView = isHeader ? headerView : bodyView;
parent = AXUIElementCreateWithHIObjectAndIdentifier((HIObjectRef)parentView, 0);
if (parent == NULL) {
return eventNotHandledErr;
@ -676,7 +741,7 @@ OSStatus BOINCListAccessibilityEventHandler( EventHandlerCallRef inHandlerCallRe
// Return the size of this part as an HISize.
size.width = pList->GetColumnWidth(col);
if (isHeader) {
size.height = pList->GetHeaderHeight();
size.height = pList->m_headerHeight;
} else { // ! isHeader
pList->GetItemRect(row, r);
size.height = r.height;
@ -703,7 +768,7 @@ OSStatus BOINCListAccessibilityEventHandler( EventHandlerCallRef inHandlerCallRe
// Now convert to global coordinates
pList->ClientToScreen(&x, &y);
pt.x = x;
pt.y = y - pList->GetHeaderHeight();
pt.y = y - pList->m_headerHeight;
SetEventParameter(inEvent, kEventParamAccessibleAttributeValue, typeHIPoint, sizeof(HIPoint), &pt);
return noErr;
@ -859,8 +924,10 @@ OSStatus BOINCListAccessibilityEventHandler( EventHandlerCallRef inHandlerCallRe
event.m_col = col;
pList->AddPendingEvent(event);
} else {
pView->ClearSelections();
pList->SelectRow(row, true);
if (pView) {
pView->ClearSelections();
}
pList->SetItemState(row, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
}
return noErr;
}

View File

@ -17,5 +17,21 @@
// macAccessiblity.h
#ifndef _MACACCESSIBILITY_H_
#define _MACACCESSIBILITY_H_
#include "BOINCBaseView.h"
#include "DlgEventLog.h"
#include "wx/generic/listctrl.h"
struct ListAccessData {
wxGenericListCtrl* pList;
CBOINCBaseView* pView;
CDlgEventLog* pEventLog;
HIViewRef headerView;
HIViewRef bodyView;
};
void AccessibilityIgnoreAllChildren(HIViewRef parent, int recursionLevel);
#endif