Related tdf#158914: fix memory leaks by calling (auto)release selectors

Found the following memory leaks using Xcode's Instruments application:

1. Posting an NSAccessibilityUIElementDestroyedNotification
   notification causes [ AquaA11yWrapper isAccessibilityElement ]
   to be called on the object so mark the object as disposed
   before posting the destroyed notification and test for disposed
   in all of the standard NSAccessibility selectors to prevent
   any calls to likely disposed C++ accessibility objects.

2. In [ AquaA11yWrapper accessibilityHitTest: ],
   [ AquaA11yFactory wrapperForAccessibleContext: ] already retains
   the returned object so retaining it until the next call to this
   selector can lead to a memory leak when dragging selected cells
   in Calc to a new location. So autorelease the object so that
   transient objects stay alive but not past the next clearing of
   the autorelease pool.

3. [ AquaA11ySelectionWrapper selectedChildrenAttributeForElement: ] is
   expected to return an autoreleased object.

4. [ AquaA11yFactory wrapperForAccessible: ] is not a getter. It
   expects the caller to release the returned object.

5. CreateNSString() is not a getter. It expects the caller to
   release the returned string.

Change-Id: I824740d7e3851b0c3e31e2c009860aa822c94222
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/168034
Reviewed-by: Patrick Luby <guibomacdev@gmail.com>
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Tested-by: Jenkins
diff --git a/vcl/inc/osx/a11ywrapper.h b/vcl/inc/osx/a11ywrapper.h
index 1eb4039..48fdd8e 100644
--- a/vcl/inc/osx/a11ywrapper.h
+++ b/vcl/inc/osx/a11ywrapper.h
@@ -67,6 +67,7 @@ struct ReferenceWrapper
    ReferenceWrapper maReferenceWrapper;
    BOOL mActsAsRadioGroup;
    BOOL mIsTableCell;
    BOOL mIsDisposed;
}
// NSAccessibility Protocol
-(id)accessibilityAttributeValue:(NSString *)attribute;
@@ -101,6 +102,7 @@ struct ReferenceWrapper
-(NSWindow*)windowForParent;
-(id)init;
-(id)initWithAccessibleContext: (css::uno::Reference < css::accessibility::XAccessibleContext >) anAccessibleContext;
-(void)setDisposed;
-(void) setDefaults: (css::uno::Reference < css::accessibility::XAccessibleContext >) rxAccessibleContext;
+(void)setPopupMenuOpen:(BOOL)popupMenuOpen;
-(css::accessibility::XAccessibleAction *)accessibleAction;
diff --git a/vcl/osx/a11yactionwrapper.mm b/vcl/osx/a11yactionwrapper.mm
index 9bea25c..77d670c 100644
--- a/vcl/osx/a11yactionwrapper.mm
+++ b/vcl/osx/a11yactionwrapper.mm
@@ -55,7 +55,10 @@
    NSMutableArray * actionNames = [ [ NSMutableArray alloc ] init ];
    if ( [ wrapper accessibleAction ] ) {
        for ( int cnt = 0; cnt < [ wrapper accessibleAction ] -> getAccessibleActionCount(); cnt++ ) {
            [ actionNames addObject: [ AquaA11yActionWrapper nativeActionNameFor: CreateNSString ( [ wrapper accessibleAction ] -> getAccessibleActionDescription ( cnt ) ) ] ];
            // Related tdf#158914: explicitly call autorelease selector
            // CreateNSString() is not a getter. It expects the caller to
            // release the returned string.
            [ actionNames addObject: [ AquaA11yActionWrapper nativeActionNameFor: [ CreateNSString ( [ wrapper accessibleAction ] -> getAccessibleActionDescription ( cnt ) ) autorelease ] ] ];
        }
    }
    return actionNames;
@@ -64,7 +67,10 @@
+(void)doAction:(NSString *)action ofElement:(AquaA11yWrapper *)wrapper {
    if ( [ wrapper accessibleAction ] ) {
        for ( int cnt = 0; cnt < [ wrapper accessibleAction ] -> getAccessibleActionCount(); cnt++ ) {
            if ( [ action isEqualToString: [ AquaA11yActionWrapper nativeActionNameFor: CreateNSString ( [ wrapper accessibleAction ] -> getAccessibleActionDescription ( cnt ) ) ] ] ) {
            // Related tdf#158914: explicitly call autorelease selector
            // CreateNSString() is not a getter. It expects the caller to
            // release the returned string.
            if ( [ action isEqualToString: [ AquaA11yActionWrapper nativeActionNameFor: [ CreateNSString ( [ wrapper accessibleAction ] -> getAccessibleActionDescription ( cnt ) ) autorelease ] ] ] ) {
                [ wrapper accessibleAction ] -> doAccessibleAction ( cnt );
                break;
            }
diff --git a/vcl/osx/a11ycomponentwrapper.mm b/vcl/osx/a11ycomponentwrapper.mm
index d9d6db1..15363a6 100644
--- a/vcl/osx/a11ycomponentwrapper.mm
+++ b/vcl/osx/a11ycomponentwrapper.mm
@@ -48,7 +48,10 @@ using namespace ::com::sun::star::uno;

+(id)descriptionAttributeForElement:(AquaA11yWrapper *)wrapper {
    if ( [ wrapper accessibleExtendedComponent ] ) {
        return CreateNSString ( [ wrapper accessibleExtendedComponent ] -> getToolTipText() );
        // Related tdf#158914: explicitly call autorelease selector
        // CreateNSString() is not a getter. It expects the caller to
        // release the returned string.
        return [ CreateNSString ( [ wrapper accessibleExtendedComponent ] -> getToolTipText() ) autorelease ];
    } else {
        return nil;
    }
diff --git a/vcl/osx/a11yfactory.mm b/vcl/osx/a11yfactory.mm
index 0783252..27b5ad2 100644
--- a/vcl/osx/a11yfactory.mm
+++ b/vcl/osx/a11yfactory.mm
@@ -140,7 +140,6 @@ static bool enabled = false; 
        } else {
            aWrapper = [ [ AquaA11yWrapper alloc ] initWithAccessibleContext: rxAccessibleContext ];
        }
        [ nativeRole release ];
        [ aWrapper setActsAsRadioGroup: asRadioGroup ];
        #if 0
        /* #i102033# NSAccessibility does not seemt to know an equivalent for transient children.
@@ -169,8 +168,8 @@ static bool enabled = false; 
    // TODO: when RADIO_BUTTON search for associated RadioGroup-wrapper and delete that as well
    AquaA11yWrapper * theWrapper = [ AquaA11yFactory wrapperForAccessibleContext: rxAccessibleContext createIfNotExists: NO ];
    if ( theWrapper != nil ) {
        NSAccessibilityPostNotification( theWrapper, NSAccessibilityUIElementDestroyedNotification );
        [ [ AquaA11yFactory allWrapper ] removeObjectForKey: [ AquaA11yFactory keyForAccessibleContext: rxAccessibleContext ] ];
        [ theWrapper setDisposed ];
        [ theWrapper release ];
    }
}
diff --git a/vcl/osx/a11yrolehelper.mm b/vcl/osx/a11yrolehelper.mm
index a1cf62f..5b621a7 100644
--- a/vcl/osx/a11yrolehelper.mm
+++ b/vcl/osx/a11yrolehelper.mm
@@ -144,17 +144,14 @@ using namespace ::com::sun::star::uno;
    id nativeRole = [ AquaA11yRoleHelper simpleMapNativeRoleFrom: accessibleContext ];
    if ( accessibleContext -> getAccessibleRole() == AccessibleRole::LABEL ) {
        if ( accessibleContext -> getAccessibleChildCount() > 0 ) {
            [ nativeRole release ];
            nativeRole = NSAccessibilityOutlineRole;
        } else if ( accessibleContext -> getAccessibleParent().is() ) {
            Reference < XAccessibleContext > rxParentContext = accessibleContext -> getAccessibleParent() -> getAccessibleContext();
            if ( rxParentContext.is() ) {
                NSString * roleParent = static_cast<NSString *>([ AquaA11yRoleHelper simpleMapNativeRoleFrom: rxParentContext.get() ]);
                if ( [ roleParent isEqualToString: NSAccessibilityOutlineRole ] ) {
                    [ nativeRole release ];
                    nativeRole = NSAccessibilityRowRole;
                }
                [ roleParent release ];
            }
        }
    } else if ( accessibleContext -> getAccessibleRole() == AccessibleRole::COMBO_BOX ) {
@@ -165,7 +162,6 @@ using namespace ::com::sun::star::uno;
                if ( rxAccessibleContext.is() && rxAccessibleContext -> getAccessibleRole() == AccessibleRole::TEXT ) {
                    sal_Int64 nStateSet = rxAccessibleContext -> getAccessibleStateSet();
                    if ( !(nStateSet & AccessibleStateType::EDITABLE ) ) {
                        [ nativeRole release ];
                        nativeRole = NSAccessibilityPopUpButtonRole;
                    }
                }
diff --git a/vcl/osx/a11yselectionwrapper.mm b/vcl/osx/a11yselectionwrapper.mm
index 9d3beee..4c9d1c7 100644
--- a/vcl/osx/a11yselectionwrapper.mm
+++ b/vcl/osx/a11yselectionwrapper.mm
@@ -34,10 +34,13 @@ using namespace ::com::sun::star::uno;
    Reference< XAccessibleSelection > xAccessibleSelection = [ wrapper accessibleSelection ];
    if( xAccessibleSelection.is() )
    {
        NSMutableArray * children = [ [ NSMutableArray alloc ] init ];
        try {
            sal_Int64 n = xAccessibleSelection -> getSelectedAccessibleChildCount();

            // Related tdf#158914: implicitly call autorelease selector
            // Callers expect this selector to return an autoreleased object.
            NSMutableArray * children = [ NSMutableArray arrayWithCapacity: n ];

            // Fix hanging when selecting a column or row in Calc
            // When a Calc column is selected, the child count will be
            // at least a million. Constructing that many C++ Calc objects
@@ -49,7 +52,12 @@ using namespace ::com::sun::star::uno;
                n = MAXIMUM_ACCESSIBLE_TABLE_CELLS;

            for ( sal_Int64 i=0 ; i < n ; ++i ) {
                [ children addObject: [ AquaA11yFactory wrapperForAccessible: xAccessibleSelection -> getSelectedAccessibleChild( i ) ] ];
                // Related tdf#158914: explicitly call release selector
                // [ AquaA11yFactory wrapperForAccessible: ] is not a getter.
                // It expects the caller to release the returned object.
                id child_wrapper = [ AquaA11yFactory wrapperForAccessible: xAccessibleSelection -> getSelectedAccessibleChild( i ) ];
                [ children addObject: child_wrapper ];
                [ child_wrapper release ];
            }

            return children;
diff --git a/vcl/osx/a11ytextattributeswrapper.mm b/vcl/osx/a11ytextattributeswrapper.mm
index 4404dc6..11b205a 100644
--- a/vcl/osx/a11ytextattributeswrapper.mm
+++ b/vcl/osx/a11ytextattributeswrapper.mm
@@ -210,7 +210,10 @@ using namespace ::com::sun::star::uno;
            } else if ( property.Name == "CharFontName" ) {
                OUString fontname;
                property.Value >>= fontname;
                [fontDescriptor setName:CreateNSString(fontname)];
                // Related tdf#158914: explicitly call autorelease selector
                // CreateNSString() is not a getter. It expects the caller to
                // release the returned string.
                [ fontDescriptor setName: [ CreateNSString(fontname) autorelease ] ];
            } else if ( property.Name == "CharWeight" ) {
                [fontDescriptor setBold:[AquaA11yTextAttributesWrapper convertBoldStyle:property]];
            } else if ( property.Name == "CharPosture" ) {
@@ -313,8 +316,11 @@ using namespace ::com::sun::star::uno;
    int endIndex = loc + len;
    int currentIndex = loc;
    try {
        NSString * myString = CreateNSString ( [ wrapper accessibleText ] -> getText() ); // TODO: dirty fix for i87817
        string = [ [ NSMutableAttributedString alloc ] initWithString: CreateNSString ( [ wrapper accessibleText ] -> getTextRange ( loc, loc + len ) ) ];
        // Related tdf#158914: explicitly call autorelease selector
        // CreateNSString() is not a getter. It expects the caller to
        // release the returned string.
        NSString * myString = [ CreateNSString ( [ wrapper accessibleText ] -> getText() ) autorelease ]; // TODO: dirty fix for i87817
        string = [ [ NSMutableAttributedString alloc ] initWithString: [ CreateNSString ( [ wrapper accessibleText ] -> getTextRange ( loc, loc + len ) ) autorelease ] ];
        [ string autorelease ];
        if ( [ wrapper accessibleTextAttributes ] && [myString characterAtIndex:0] != 57361) { // TODO: dirty fix for i87817
            [ string beginEditing ];
diff --git a/vcl/osx/a11ytextwrapper.mm b/vcl/osx/a11ytextwrapper.mm
index cfd4ae7..5a932d3 100644
--- a/vcl/osx/a11ytextwrapper.mm
+++ b/vcl/osx/a11ytextwrapper.mm
@@ -39,7 +39,10 @@ using namespace ::com::sun::star::uno;
@implementation AquaA11yTextWrapper : NSObject

+(id)valueAttributeForElement:(AquaA11yWrapper *)wrapper {
    return CreateNSString ( [ wrapper accessibleText ] -> getText() );
    // Related tdf#158914: explicitly call autorelease selector
    // CreateNSString() is not a getter. It expects the caller to
    // release the returned string.
    return [ CreateNSString ( [ wrapper accessibleText ] -> getText() ) autorelease ];
}

+(void)setValueAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value
@@ -54,7 +57,10 @@ using namespace ::com::sun::star::uno;
}

+(id)selectedTextAttributeForElement:(AquaA11yWrapper *)wrapper {
    return CreateNSString ( [ wrapper accessibleText ] -> getSelectedText() );
    // Related tdf#158914: explicitly call autorelease selector
    // CreateNSString() is not a getter. It expects the caller to
    // release the returned string.
    return [ CreateNSString ( [ wrapper accessibleText ] -> getSelectedText() ) autorelease ];
}

+(void)setSelectedTextAttributeForElement:(AquaA11yWrapper *)wrapper to:(id)value {
@@ -175,9 +181,12 @@ using namespace ::com::sun::star::uno;
+(id)stringForRangeAttributeForElement:(AquaA11yWrapper *)wrapper forParameter:(id)range {
    int loc = [ range rangeValue ].location;
    int len = [ range rangeValue ].length;
    NSMutableString * textRange = [ [ NSMutableString alloc ] init ];
    NSMutableString * textRange = [ NSMutableString string ];
    try {
        [ textRange appendString: CreateNSString ( [ wrapper accessibleText ] -> getTextRange ( loc, loc + len ) ) ];
        // Related tdf#158914: explicitly call autorelease selector
        // CreateNSString() is not a getter. It expects the caller to
        // release the returned string.
        [ textRange appendString: [ CreateNSString ( [ wrapper accessibleText ] -> getTextRange ( loc, loc + len ) ) autorelease ] ];
    } catch ( IndexOutOfBoundsException & ) {
        // empty
    }
diff --git a/vcl/osx/a11ywrapper.mm b/vcl/osx/a11ywrapper.mm
index 9680841..3793b32 100644
--- a/vcl/osx/a11ywrapper.mm
+++ b/vcl/osx/a11ywrapper.mm
@@ -84,10 +84,28 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) {
    return self;
}

-(void)setDisposed {
    // Related: tdf#148453 Acquire solar mutex during native accessibility calls
    SolarMutexGuard aGuard;

    mIsDisposed = YES;

    // Release all strong C++ references
    maReferenceWrapper = ReferenceWrapper();

    // Related tdf@158914 avoid resurrecting object's C++ references
    // Posting an NSAccessibilityUIElementDestroyedNotification
    // notification causes [ AquaA11yWrapper isAccessibilityElement ]
    // to be called on the object so mark the object as disposed
    // before posting the destroyed notification.
    NSAccessibilityPostNotification( self, NSAccessibilityUIElementDestroyedNotification );
}

-(void) setDefaults: (Reference < XAccessibleContext >) rxAccessibleContext {
    mActsAsRadioGroup = NO;
    maReferenceWrapper.rAccessibleContext = rxAccessibleContext;
    mIsTableCell = NO;
    mIsDisposed = NO;
    // Querying all supported interfaces
    try {
        // XAccessibleComponent
@@ -230,7 +248,6 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) {
        if ( ! [ subRole isEqualToString: @"" ] ) {
            return subRole;
        } else {
            [ subRole release ];
            SAL_WNODEPRECATED_DECLARATIONS_PUSH
                //TODO: 10.10 accessibilityAttributeValue:
            return [ super accessibilityAttributeValue: NSAccessibilitySubroleAttribute ];
@@ -240,7 +257,10 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) {
}

-(id)titleAttribute {
    return CreateNSString ( [ self accessibleContext ] -> getAccessibleName() );
    // Related tdf#158914: explicitly call autorelease selector
    // CreateNSString() is not a getter. It expects the caller to
    // release the returned string.
    return [ CreateNSString ( [ self accessibleContext ] -> getAccessibleName() ) autorelease ];
}

-(id)descriptionAttribute {
@@ -249,7 +269,10 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) {
    } else if ( [ self accessibleExtendedComponent ] ) {
        return [ AquaA11yComponentWrapper descriptionAttributeForElement: self ];
    } else {
        return CreateNSString ( [ self accessibleContext ] -> getAccessibleDescription() );
        // Related tdf#158914: explicitly call autorelease selector
        // CreateNSString() is not a getter. It expects the caller to
        // release the returned string.
        return [ CreateNSString ( [ self accessibleContext ] -> getAccessibleDescription() ) autorelease ];
    }
}

@@ -425,7 +448,10 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) {
}

-(id)helpAttribute {
    return CreateNSString ( [ self accessibleContext ] -> getAccessibleDescription() );
    // Related tdf#158914: explicitly call autorelease selector
    // CreateNSString() is not a getter. It expects the caller to
    // release the returned string.
    return [ CreateNSString ( [ self accessibleContext ] -> getAccessibleDescription() ) autorelease ];
}

-(id)roleDescriptionAttribute {
@@ -449,15 +475,11 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) {
        // build string
        NSNumber * nIndex = [ NSNumber numberWithInt: index ];
        NSNumber * nGroupsize = [ NSNumber numberWithInt: [ children count ] ];
        NSMutableString * value = [ [ NSMutableString alloc ] init ];
        NSMutableString * value = [ NSMutableString string ];
        [ value appendString: @"radio button " ];
        [ value appendString: [ nIndex stringValue ] ];
        [ value appendString: @" of " ];
        [ value appendString: [ nGroupsize stringValue ] ];
        // clean up and return string
        [ nIndex release ];
        [ nGroupsize release ];
        [ children release ];
        return value;
    } else {
        return [ AquaA11yRoleHelper getRoleDescriptionFrom:
@@ -642,9 +664,6 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) {
                titleElement = [ AquaA11yFactory wrapperForAccessibleContext: rxAccessible -> getAccessibleContext() ];
            }
        }
        if ( title ) {
            [ title release ];
        }
        return titleElement;
    } else {
        return nil;
@@ -687,6 +706,8 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) {
-(id)accessibilityAttributeValue:(NSString *)attribute {
    // Related: tdf#148453 Acquire solar mutex during native accessibility calls
    SolarMutexGuard aGuard;
    if ( mIsDisposed )
        return nil;

    SAL_INFO("vcl.a11y", "[" << self << " accessibilityAttributeValue:" << attribute << "]");
    // #i90575# guard NSAccessibility protocol against unwanted access
@@ -720,13 +741,15 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) {
-(BOOL)accessibilityIsIgnored {
    // Related: tdf#148453 Acquire solar mutex during native accessibility calls
    SolarMutexGuard aGuard;
    if ( mIsDisposed )
        return YES;

    SAL_INFO("vcl.a11y", "[" << self << " accessibilityIsIgnored]");
    // #i90575# guard NSAccessibility protocol against unwanted access
    if ( isPopupMenuOpen ) {
        return NO;
    }
    bool ignored = false;
    BOOL ignored = false;
    try {
        sal_Int16 nRole = [ self accessibleContext ] -> getAccessibleRole();
        switch ( nRole ) {
@@ -754,6 +777,8 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) {
-(NSArray *)accessibilityAttributeNames {
    // Related: tdf#148453 Acquire solar mutex during native accessibility calls
    SolarMutexGuard aGuard;
    if ( mIsDisposed )
        return nil;

    SAL_INFO("vcl.a11y", "[" << self << " accessibilityAttributeNames]");
    // #i90575# guard NSAccessibility protocol against unwanted access
@@ -817,21 +842,9 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) {
        if ( [ self accessibleValue ] ) {
            [ AquaA11yValueWrapper addAttributeNamesTo: attributeNames ];
        }
        if ( nativeSubrole ) {
            [ nativeSubrole release ];
        }
        if ( title ) {
            [ title release ];
        }
        // Related: tdf#153374 Don't release autoreleased attributeNames
        return attributeNames;
    } catch ( DisposedException & ) { // Object is no longer available
        if ( nativeSubrole ) {
            [ nativeSubrole release ];
        }
        if ( title ) {
            [ title release ];
        }
        // Related: tdf#153374 Don't release autoreleased attributeNames
        // Also, return an autoreleased empty array instead of a retained array.
        [ AquaA11yFactory removeFromWrapperRepositoryFor: [ self accessibleContext ] ];
@@ -842,6 +855,8 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) {
-(BOOL)accessibilityIsAttributeSettable:(NSString *)attribute {
    // Related: tdf#148453 Acquire solar mutex during native accessibility calls
    SolarMutexGuard aGuard;
    if ( mIsDisposed )
        return NO;

    SAL_INFO("vcl.a11y", "[" << self << " accessibilityAttributeIsSettable:" << attribute << "]");
    bool isSettable = false;
@@ -863,6 +878,8 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) {
-(NSArray *)accessibilityParameterizedAttributeNames {
    // Related: tdf#148453 Acquire solar mutex during native accessibility calls
    SolarMutexGuard aGuard;
    if ( mIsDisposed )
        return [ NSArray array ];

    SAL_INFO("vcl.a11y", "[" << self << " accessibilityParameterizedAttributeNames]");
    NSMutableArray * attributeNames = [ NSMutableArray array ];
@@ -876,6 +893,8 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) {
-(id)accessibilityAttributeValue:(NSString *)attribute forParameter:(id)parameter {
    // Related: tdf#148453 Acquire solar mutex during native accessibility calls
    SolarMutexGuard aGuard;
    if ( mIsDisposed )
        return nil;

    SAL_INFO("vcl.a11y", "[" << self << " accessibilityAttributeValue:" << attribute << " forParameter:" << (static_cast<NSObject*>(parameter)) << "]");
    SEL methodSelector = [ self selectorForAttribute: attribute asGetter: YES withGetterParameter: YES ];
@@ -902,6 +921,8 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) {
-(void)accessibilitySetValue:(id)value forAttribute:(NSString *)attribute {
    // Related: tdf#148453 Acquire solar mutex during native accessibility calls
    SolarMutexGuard aGuard;
    if ( mIsDisposed )
        return;

    SAL_INFO("vcl.a11y", "[" << self << " accessibilitySetValue:" << (static_cast<NSObject*>(value)) << " forAttribute:" << attribute << "]");
    SEL methodSelector = [ self selectorForAttribute: attribute asGetter: NO withGetterParameter: NO ];
@@ -922,6 +943,8 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) {
-(id)accessibilityFocusedUIElement {
    // Related: tdf#148453 Acquire solar mutex during native accessibility calls
    SolarMutexGuard aGuard;
    if ( mIsDisposed )
        return nil;

    SAL_INFO("vcl.a11y", "[" << self << " accessibilityFocusedUIElement]");
    // #i90575# guard NSAccessibility protocol against unwanted access
@@ -976,9 +999,6 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) {
    } else if ( enabled && [ self accessibleAction ] ) {
        wrapper = self ;
    }
    [ parentRole release ];
    [ enabledAttr release ];
    [ role release ];
    return wrapper;
}

@@ -989,6 +1009,8 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) {
-(BOOL)performAction:(NSString *)action {
    // Related: tdf#148453 Acquire solar mutex during native accessibility calls
    SolarMutexGuard aGuard;
    if ( mIsDisposed )
        return NO;

    SAL_INFO("vcl.a11y", "[" << self << " accessibilityPerformAction:" << action << "]");
    AquaA11yWrapper * actionResponder = [ self actionResponder ];
@@ -1002,6 +1024,8 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) {
-(NSArray *)accessibilityActionNames {
    // Related: tdf#148453 Acquire solar mutex during native accessibility calls
    SolarMutexGuard aGuard;
    if ( mIsDisposed )
        return nil;

    SAL_INFO("vcl.a11y", "[" << self << " accessibilityActionNames]");
    NSArray * actionNames = nil;
@@ -1009,7 +1033,7 @@ static std::ostream &operator<<(std::ostream &s, NSObject *obj) {
    if ( actionResponder ) {
        actionNames = [ AquaA11yActionWrapper actionNamesForElement: actionResponder ];
    } else {
        actionNames = [ [ NSArray alloc ] init ];
        actionNames = [ NSArray array ];
    }
    return actionNames;
}
@@ -1096,13 +1120,10 @@ static Reference < XAccessibleContext > hitTestRunner ( css::awt::Point point,
-(id)accessibilityHitTest:(NSPoint)point {
    // Related: tdf#148453 Acquire solar mutex during native accessibility calls
    SolarMutexGuard aGuard;
    if ( mIsDisposed )
        return nil;

    SAL_INFO("vcl.a11y", "[" << self << " accessibilityHitTest:" << point << "]");
    static id wrapper = nil;
    if ( nil != wrapper ) {
        [ wrapper release ];
        wrapper = nil;
    }
    Reference < XAccessibleContext > hitChild;
    NSRect screenRect = [ [ NSScreen mainScreen ] frame ];
    css::awt::Point hitPoint ( static_cast<sal_Int32>(point.x) , static_cast<sal_Int32>(screenRect.size.height - point.y) );
@@ -1139,12 +1160,16 @@ static Reference < XAccessibleContext > hitTestRunner ( css::awt::Point point,
        hitChild = hitTestRunner ( hitPoint, maReferenceWrapper.rAccessibleContext );
    }
    if ( hitChild.is() ) {
        wrapper = [ AquaA11yFactory wrapperForAccessibleContext: hitChild ];
        // Related tdf#158914: do not retain wrapper
        // [ AquaA11yFactory wrapperForAccessibleContext: ] already retains
        // the returned object so retaining it until the next call to this
        // selector can lead to a memory leak when dragging selected cells
        // in Calc to a new location. So autorelease the object so that
        // transient objects stay alive but not past the next clearing of
        // the autorelease pool.
        return [ [ AquaA11yFactory wrapperForAccessibleContext: hitChild ] autorelease ];
    }
    if ( wrapper ) {
        [ wrapper retain ]; // TODO: retain only when transient ?
    }
    return wrapper;
    return nil;
}

#pragma mark -
@@ -1546,6 +1571,8 @@ static Reference < XAccessibleContext > hitTestRunner ( css::awt::Point point,
{
    // Related: tdf#148453 Acquire solar mutex during native accessibility calls
    SolarMutexGuard aGuard;
    if ( mIsDisposed )
        return NSZeroRect;

    try {
        XAccessibleComponent *pAccessibleComponent = [ self accessibleComponent ];
@@ -1576,6 +1603,11 @@ static Reference < XAccessibleContext > hitTestRunner ( css::awt::Point point,
    // don't explicitly report (non-)expanded state when not expandable
    if (aSelector == @selector(isAccessibilityExpanded))
    {
        // Acquire solar mutex during native accessibility calls
        SolarMutexGuard aGuard;
        if ( mIsDisposed )
            return NO;

        const sal_Int64 nStateSet = [ self accessibleContext ] -> getAccessibleStateSet();
        if (!( nStateSet & AccessibleStateType::EXPANDABLE))
            return false;
diff --git a/vcl/osx/a11ywrapperbutton.mm b/vcl/osx/a11ywrapperbutton.mm
index a2c0d03..d988e0b 100644
--- a/vcl/osx/a11ywrapperbutton.mm
+++ b/vcl/osx/a11ywrapperbutton.mm
@@ -39,6 +39,8 @@
-(NSArray *)accessibilityAttributeNames {
    // Related: tdf#148453 Acquire solar mutex during native accessibility calls
    SolarMutexGuard aGuard;
    if ( mIsDisposed )
        return [ NSArray array ];

    // Default Attributes
    NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ];
diff --git a/vcl/osx/a11ywrappercheckbox.mm b/vcl/osx/a11ywrappercheckbox.mm
index 9e0f221..7f78e68 100644
--- a/vcl/osx/a11ywrappercheckbox.mm
+++ b/vcl/osx/a11ywrappercheckbox.mm
@@ -39,6 +39,8 @@
-(BOOL)accessibilityIsAttributeSettable:(NSString *)attribute {
    // Related: tdf#148453 Acquire solar mutex during native accessibility calls
    SolarMutexGuard aGuard;
    if ( mIsDisposed )
        return NO;

    if ( [ attribute isEqualToString: NSAccessibilityValueAttribute ] ) {
        return NO;
@@ -49,6 +51,8 @@
-(NSArray *)accessibilityAttributeNames {
    // Related: tdf#148453 Acquire solar mutex during native accessibility calls
    SolarMutexGuard aGuard;
    if ( mIsDisposed )
        return [ NSArray array ];

    // Default Attributes
    NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ];
diff --git a/vcl/osx/a11ywrappercombobox.mm b/vcl/osx/a11ywrappercombobox.mm
index bfcef72..d9a0727 100644
--- a/vcl/osx/a11ywrappercombobox.mm
+++ b/vcl/osx/a11ywrappercombobox.mm
@@ -113,6 +113,8 @@ using namespace ::com::sun::star::uno;
-(BOOL)accessibilityIsAttributeSettable:(NSString *)attribute {
    // Related: tdf#148453 Acquire solar mutex during native accessibility calls
    SolarMutexGuard aGuard;
    if ( mIsDisposed )
        return NO;

    if ( [ self textArea ] != nil && (
         [ attribute isEqualToString: NSAccessibilitySelectedTextAttribute ]
@@ -126,6 +128,8 @@ using namespace ::com::sun::star::uno;
-(void)accessibilitySetValue:(id)value forAttribute:(NSString *)attribute {
    // Related: tdf#148453 Acquire solar mutex during native accessibility calls
    SolarMutexGuard aGuard;
    if ( mIsDisposed )
        return;

    if ( [ self textArea ] != nil && (
         [ attribute isEqualToString: NSAccessibilitySelectedTextAttribute ]
@@ -139,6 +143,8 @@ using namespace ::com::sun::star::uno;
-(NSArray *)accessibilityAttributeNames {
    // Related: tdf#148453 Acquire solar mutex during native accessibility calls
    SolarMutexGuard aGuard;
    if ( mIsDisposed )
        return [ NSArray array ];

    // Default Attributes
    NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ];
diff --git a/vcl/osx/a11ywrappergroup.mm b/vcl/osx/a11ywrappergroup.mm
index 7ed70d4..f50d236 100644
--- a/vcl/osx/a11ywrappergroup.mm
+++ b/vcl/osx/a11ywrappergroup.mm
@@ -33,6 +33,8 @@
-(NSArray *)accessibilityAttributeNames {
    // Related: tdf#148453 Acquire solar mutex during native accessibility calls
    SolarMutexGuard aGuard;
    if ( mIsDisposed )
        return [ NSArray array ];

    // Default Attributes
    NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ];
diff --git a/vcl/osx/a11ywrapperlist.mm b/vcl/osx/a11ywrapperlist.mm
index 25b3fa3..e1c3f4f 100644
--- a/vcl/osx/a11ywrapperlist.mm
+++ b/vcl/osx/a11ywrapperlist.mm
@@ -31,6 +31,8 @@ using namespace ::com::sun::star::accessibility;
-(NSArray *)accessibilityAttributeNames {
    // Related: tdf#148453 Acquire solar mutex during native accessibility calls
    SolarMutexGuard aGuard;
    if ( mIsDisposed )
        return [ NSArray array ];

    // Default Attributes
    NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ];
diff --git a/vcl/osx/a11ywrapperradiobutton.mm b/vcl/osx/a11ywrapperradiobutton.mm
index 5022cc1..bd2d8bd 100644
--- a/vcl/osx/a11ywrapperradiobutton.mm
+++ b/vcl/osx/a11ywrapperradiobutton.mm
@@ -38,6 +38,8 @@
-(BOOL)accessibilityIsAttributeSettable:(NSString *)attribute {
    // Related: tdf#148453 Acquire solar mutex during native accessibility calls
    SolarMutexGuard aGuard;
    if ( mIsDisposed )
        return NO;

    if ( [ attribute isEqualToString: NSAccessibilityValueAttribute ] ) {
        return NO;
@@ -48,6 +50,8 @@
-(NSArray *)accessibilityAttributeNames {
    // Related: tdf#148453 Acquire solar mutex during native accessibility calls
    SolarMutexGuard aGuard;
    if ( mIsDisposed )
        return [ NSArray array ];

    // Default Attributes
    NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ];
diff --git a/vcl/osx/a11ywrapperradiogroup.mm b/vcl/osx/a11ywrapperradiogroup.mm
index 9768dbb..0896439 100644
--- a/vcl/osx/a11ywrapperradiogroup.mm
+++ b/vcl/osx/a11ywrapperradiogroup.mm
@@ -30,6 +30,8 @@
-(NSArray *)accessibilityAttributeNames {
    // Related: tdf#148453 Acquire solar mutex during native accessibility calls
    SolarMutexGuard aGuard;
    if ( mIsDisposed )
        return [ NSArray array ];

    // Default Attributes
    NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ];
diff --git a/vcl/osx/a11ywrapperrow.mm b/vcl/osx/a11ywrapperrow.mm
index 0c140c8..a00e210 100644
--- a/vcl/osx/a11ywrapperrow.mm
+++ b/vcl/osx/a11ywrapperrow.mm
@@ -36,6 +36,8 @@
-(NSArray *)accessibilityAttributeNames {
    // Related: tdf#148453 Acquire solar mutex during native accessibility calls
    SolarMutexGuard aGuard;
    if ( mIsDisposed )
        return [ NSArray array ];

    // Default Attributes
    NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ];
diff --git a/vcl/osx/a11ywrapperscrollarea.mm b/vcl/osx/a11ywrapperscrollarea.mm
index 2203722..4fa30a9 100644
--- a/vcl/osx/a11ywrapperscrollarea.mm
+++ b/vcl/osx/a11ywrapperscrollarea.mm
@@ -62,6 +62,8 @@
-(NSArray *)accessibilityAttributeNames {
    // Related: tdf#148453 Acquire solar mutex during native accessibility calls
    SolarMutexGuard aGuard;
    if ( mIsDisposed )
        return [ NSArray array ];

    // Default Attributes
    NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ];
diff --git a/vcl/osx/a11ywrapperscrollbar.mm b/vcl/osx/a11ywrapperscrollbar.mm
index 4a4612d..8117e39 100644
--- a/vcl/osx/a11ywrapperscrollbar.mm
+++ b/vcl/osx/a11ywrapperscrollbar.mm
@@ -34,6 +34,8 @@ using namespace ::com::sun::star::accessibility;
-(NSArray *)accessibilityAttributeNames {
    // Related: tdf#148453 Acquire solar mutex during native accessibility calls
    SolarMutexGuard aGuard;
    if ( mIsDisposed )
        return [ NSArray array ];

    // Default Attributes
    NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ];
diff --git a/vcl/osx/a11ywrappersplitter.mm b/vcl/osx/a11ywrappersplitter.mm
index 39ec496..993d8a0 100644
--- a/vcl/osx/a11ywrappersplitter.mm
+++ b/vcl/osx/a11ywrappersplitter.mm
@@ -31,6 +31,8 @@ using namespace ::com::sun::star::accessibility;
-(NSArray *)accessibilityAttributeNames {
    // Related: tdf#148453 Acquire solar mutex during native accessibility calls
    SolarMutexGuard aGuard;
    if ( mIsDisposed )
        return [ NSArray array ];

    // Default Attributes
    NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ];
diff --git a/vcl/osx/a11ywrapperstatictext.mm b/vcl/osx/a11ywrapperstatictext.mm
index 114c417..317de60 100644
--- a/vcl/osx/a11ywrapperstatictext.mm
+++ b/vcl/osx/a11ywrapperstatictext.mm
@@ -37,6 +37,8 @@
-(NSArray *)accessibilityAttributeNames {
    // Related: tdf#148453 Acquire solar mutex during native accessibility calls
    SolarMutexGuard aGuard;
    if ( mIsDisposed )
        return [ NSArray array ];

    // Default Attributes
    NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ];
diff --git a/vcl/osx/a11ywrappertabgroup.mm b/vcl/osx/a11ywrappertabgroup.mm
index 3d32ccc..de484a5 100644
--- a/vcl/osx/a11ywrappertabgroup.mm
+++ b/vcl/osx/a11ywrappertabgroup.mm
@@ -29,6 +29,8 @@
-(NSArray *)accessibilityAttributeNames {
    // Related: tdf#148453 Acquire solar mutex during native accessibility calls
    SolarMutexGuard aGuard;
    if ( mIsDisposed )
        return [ NSArray array ];

    // Default Attributes
    NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ];
diff --git a/vcl/osx/a11ywrappertextarea.mm b/vcl/osx/a11ywrappertextarea.mm
index 354030f..a53550f 100644
--- a/vcl/osx/a11ywrappertextarea.mm
+++ b/vcl/osx/a11ywrappertextarea.mm
@@ -29,6 +29,8 @@
-(NSArray *)accessibilityAttributeNames {
    // Related: tdf#148453 Acquire solar mutex during native accessibility calls
    SolarMutexGuard aGuard;
    if ( mIsDisposed )
        return [ NSArray array ];

    // Default Attributes
    NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ];
diff --git a/vcl/osx/a11ywrappertoolbar.mm b/vcl/osx/a11ywrappertoolbar.mm
index 28b5d01..e2d0ec5 100644
--- a/vcl/osx/a11ywrappertoolbar.mm
+++ b/vcl/osx/a11ywrappertoolbar.mm
@@ -29,6 +29,8 @@
-(NSArray *)accessibilityAttributeNames {
    // Related: tdf#148453 Acquire solar mutex during native accessibility calls
    SolarMutexGuard aGuard;
    if ( mIsDisposed )
        return [ NSArray array ];

    // Default Attributes
    NSMutableArray * attributeNames = [ NSMutableArray arrayWithArray: [ super accessibilityAttributeNames ] ];
diff --git a/vcl/osx/salmenu.cxx b/vcl/osx/salmenu.cxx
index 6ea16a6..800affc 100644
--- a/vcl/osx/salmenu.cxx
+++ b/vcl/osx/salmenu.cxx
@@ -163,6 +163,7 @@ static void initAppMenu()
    pNewItem = [pAppMenu addItemWithTitle: pString
        action: nil
        keyEquivalent: @""];
    [pString release];
    NSMenu *servicesMenu = [[[NSMenu alloc] initWithTitle:@"Services"] autorelease];
    [pNewItem setSubmenu: servicesMenu];
    [NSApp setServicesMenu: servicesMenu];