summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Meeks <michael.meeks@suse.com>2012-12-18 13:29:03 +0000
committerMichael Meeks <michael.meeks@suse.com>2012-12-18 16:47:14 +0000
commit1211bf4682b7e8454d86d5a812df421abf68f662 (patch)
tree75567540196c20c64b2d563b7758d0cc74d1bff1
parent28549ae77dee063da50a56eb3cdf9114365a6afd (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.cxx2
-rw-r--r--sc/source/ui/Accessibility/AccessibleTableBase.cxx20
-rw-r--r--vcl/aqua/source/a11y/aqua11ywrapper.mm37
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;
+ }
}
}
}