diff options
author | Michael Meeks <michael.meeks@suse.com> | 2012-12-18 13:29:03 +0000 |
---|---|---|
committer | Michael Meeks <michael.meeks@suse.com> | 2012-12-18 16:47:14 +0000 |
commit | 1211bf4682b7e8454d86d5a812df421abf68f662 (patch) | |
tree | 75567540196c20c64b2d563b7758d0cc74d1bff1 | |
parent | 28549ae77dee063da50a56eb3cdf9114365a6afd (diff) |
fdo#56937 - mac a11y hang related to traversing vast, broken hierarchies.
Change-Id: Iff0537a69b2c6ae929da6a05f26c0d55415d6d8a
Signed-off-by: Tor Lillqvist <tml@iki.fi>
-rw-r--r-- | sc/source/ui/Accessibility/AccessibleSpreadsheet.cxx | 2 | ||||
-rw-r--r-- | sc/source/ui/Accessibility/AccessibleTableBase.cxx | 20 | ||||
-rw-r--r-- | vcl/aqua/source/a11y/aqua11ywrapper.mm | 37 |
3 files changed, 44 insertions, 15 deletions
diff --git a/sc/source/ui/Accessibility/AccessibleSpreadsheet.cxx b/sc/source/ui/Accessibility/AccessibleSpreadsheet.cxx index 0408458f9704..cf29eaecce39 100644 --- a/sc/source/ui/Accessibility/AccessibleSpreadsheet.cxx +++ b/sc/source/ui/Accessibility/AccessibleSpreadsheet.cxx @@ -55,6 +55,8 @@ using namespace ::com::sun::star::accessibility; //===== internal ============================================================ +// FIXME: really unclear why we have an ScAccessibleTableBase with +// only this single sub-class ScAccessibleSpreadsheet::ScAccessibleSpreadsheet( ScAccessibleDocument* pAccDoc, ScTabViewShell* pViewShell, diff --git a/sc/source/ui/Accessibility/AccessibleTableBase.cxx b/sc/source/ui/Accessibility/AccessibleTableBase.cxx index c1408dbd005d..82203391f674 100644 --- a/sc/source/ui/Accessibility/AccessibleTableBase.cxx +++ b/sc/source/ui/Accessibility/AccessibleTableBase.cxx @@ -272,7 +272,7 @@ sal_Bool SAL_CALL ScAccessibleTableBase::isAccessibleSelected( sal_Int32 /* nRow return false; } - //===== XAccessibleExtendedTable ======================================== +// ===== XAccessibleExtendedTable ======================================== sal_Int32 SAL_CALL ScAccessibleTableBase::getAccessibleIndex( sal_Int32 nRow, sal_Int32 nColumn ) throw (uno::RuntimeException, lang::IndexOutOfBoundsException) @@ -315,7 +315,7 @@ sal_Int32 SAL_CALL ScAccessibleTableBase::getAccessibleColumn( sal_Int32 nChildI return nChildIndex % static_cast<sal_Int32>(maRange.aEnd.Col() - maRange.aStart.Col() + 1); } - //===== XAccessibleContext ============================================== +// ===== XAccessibleContext ============================================== sal_Int32 SAL_CALL ScAccessibleTableBase::getAccessibleChildCount(void) @@ -323,9 +323,16 @@ sal_Int32 SAL_CALL { SolarMutexGuard aGuard; IsObjectValid(); - return static_cast<sal_Int32>(maRange.aEnd.Row() - maRange.aStart.Row() + 1) * - (maRange.aEnd.Col() - maRange.aStart.Col() + 1); -// return 1; + + // FIXME: representing rows & columns this way is a plain and simple madness. + // this needs a radical re-think. + sal_Int64 nMax = ((sal_Int64)(maRange.aEnd.Row() - maRange.aStart.Row() + 1) * + (sal_Int64)(maRange.aEnd.Col() - maRange.aStart.Col() + 1)); + if (nMax > SAL_MAX_INT32) + nMax = SAL_MAX_INT32; + if (nMax < 0) + return 0; + return static_cast<sal_Int32>(nMax); } uno::Reference< XAccessible > SAL_CALL @@ -339,6 +346,9 @@ uno::Reference< XAccessible > SAL_CALL if (nIndex >= getAccessibleChildCount() || nIndex < 0) throw lang::IndexOutOfBoundsException(); + // FIXME: representing rows & columns this way is a plain and simple madness. + // this needs a radical re-think. + sal_Int32 nRow(0); sal_Int32 nColumn(0); sal_Int32 nTemp(maRange.aEnd.Col() - maRange.aStart.Col() + 1); diff --git a/vcl/aqua/source/a11y/aqua11ywrapper.mm b/vcl/aqua/source/a11y/aqua11ywrapper.mm index 1be3e4ae5910..a48aa5a916a1 100644 --- a/vcl/aqua/source/a11y/aqua11ywrapper.mm +++ b/vcl/aqua/source/a11y/aqua11ywrapper.mm @@ -986,21 +986,38 @@ Reference < XAccessibleContext > hitTestRunner ( com::sun::star::awt::Point poin Reference < XAccessibleComponent > rxAccessibleComponent ( rxAccessibleContext, UNO_QUERY ); if ( rxAccessibleComponent.is() ) { com::sun::star::awt::Point location = rxAccessibleComponent -> getLocationOnScreen(); - com::sun::star::awt::Point hitPoint ( point.X - location.X , point.Y - location.Y); + com::sun::star::awt::Point hitPoint ( point.X - location.X , point.Y - location.Y); Reference < XAccessible > rxAccessible = rxAccessibleComponent -> getAccessibleAtPoint ( hitPoint ); if ( rxAccessible.is() && rxAccessible -> getAccessibleContext().is() && rxAccessible -> getAccessibleContext() -> getAccessibleChildCount() == 0 ) { hitChild = rxAccessible -> getAccessibleContext(); } - } - if ( !hitChild.is() && rxAccessibleContext -> getAccessibleChildCount() > 0 ) { // special treatment for e.g. comboboxes - for ( int i = 0; i < rxAccessibleContext -> getAccessibleChildCount(); i++ ) { - Reference < XAccessible > rxAccessibleChild = rxAccessibleContext -> getAccessibleChild ( i ); - if ( rxAccessibleChild.is() && rxAccessibleChild -> getAccessibleContext().is() && rxAccessibleChild -> getAccessibleContext() -> getAccessibleRole() != AccessibleRole::LIST ) { - Reference < XAccessibleContext > myHitChild = hitTestRunner ( point, rxAccessibleChild -> getAccessibleContext() ); - if ( myHitChild.is() ) { - hitChild = myHitChild; - break; + } + + // iterate the hirerachy looking doing recursive hit testing. + // apparently necessary as a special treatment for e.g. comboboxes + if ( !hitChild.is() ) { + bool bSafeToIterate = true; + sal_Int32 nCount = rxAccessibleContext -> getAccessibleChildCount(); + + if ( nCount < 0 || nCount > SAL_MAX_UINT16 /* slow enough for anyone */ ) + bSafeToIterate = false; + else { // manages descendants is an horror from the a11y standards guys. + Reference< XAccessibleStateSet > xStateSet; + xStateSet = rxAccessibleContext -> getAccessibleStateSet(); + if (xStateSet.is() && xStateSet -> contains(AccessibleStateType::MANAGES_DESCENDANTS ) ) + bSafeToIterate = false; + } + + if( bSafeToIterate ) { + for ( int i = 0; i < rxAccessibleContext -> getAccessibleChildCount(); i++ ) { + Reference < XAccessible > rxAccessibleChild = rxAccessibleContext -> getAccessibleChild ( i ); + if ( rxAccessibleChild.is() && rxAccessibleChild -> getAccessibleContext().is() && rxAccessibleChild -> getAccessibleContext() -> getAccessibleRole() != AccessibleRole::LIST ) { + Reference < XAccessibleContext > myHitChild = hitTestRunner ( point, rxAccessibleChild -> getAccessibleContext() ); + if ( myHitChild.is() ) { + hitChild = myHitChild; + break; + } } } } |