xref: /AOO41X/main/vcl/aqua/source/a11y/aqua11ywrapper.mm (revision eae433d68a2b324b5eb43a6741035c664effb2b7)
1323de322SAndrew Rist/**************************************************************
2cdf0e10cSrcweir *
3323de322SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
4323de322SAndrew Rist * or more contributor license agreements.  See the NOTICE file
5323de322SAndrew Rist * distributed with this work for additional information
6323de322SAndrew Rist * regarding copyright ownership.  The ASF licenses this file
7323de322SAndrew Rist * to you under the Apache License, Version 2.0 (the
8323de322SAndrew Rist * "License"); you may not use this file except in compliance
9323de322SAndrew Rist * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir *
11323de322SAndrew Rist *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir *
13323de322SAndrew Rist * Unless required by applicable law or agreed to in writing,
14323de322SAndrew Rist * software distributed under the License is distributed on an
15323de322SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16323de322SAndrew Rist * KIND, either express or implied.  See the License for the
17323de322SAndrew Rist * specific language governing permissions and limitations
18323de322SAndrew Rist * under the License.
19cdf0e10cSrcweir *
20323de322SAndrew Rist *************************************************************/
21323de322SAndrew Rist
22323de322SAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir// MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir#include "precompiled_vcl.hxx"
26cdf0e10cSrcweir
27cdf0e10cSrcweir#include "aqua/salinst.h"
28cdf0e10cSrcweir#include "aqua/saldata.hxx"
29cdf0e10cSrcweir
30cdf0e10cSrcweir#include "aqua/aqua11ywrapper.h"
31cdf0e10cSrcweir#include "aqua/aqua11ylistener.hxx"
32cdf0e10cSrcweir#include "aqua/aqua11yfactory.h"
33cdf0e10cSrcweir#include "aqua/aqua11yfocustracker.hxx"
34cdf0e10cSrcweir
35cdf0e10cSrcweir#include "aqua11yfocuslistener.hxx"
36cdf0e10cSrcweir#include "aqua11yactionwrapper.h"
37cdf0e10cSrcweir#include "aqua11ycomponentwrapper.h"
38cdf0e10cSrcweir#include "aqua11yselectionwrapper.h"
39cdf0e10cSrcweir#include "aqua11ytablewrapper.h"
40cdf0e10cSrcweir#include "aqua11ytextwrapper.h"
41cdf0e10cSrcweir#include "aqua11yvaluewrapper.h"
42cdf0e10cSrcweir#include "aqua11yrolehelper.h"
43cdf0e10cSrcweir
44cdf0e10cSrcweir#include <com/sun/star/accessibility/AccessibleRole.hpp>
45cdf0e10cSrcweir#include <com/sun/star/accessibility/AccessibleStateType.hpp>
46cdf0e10cSrcweir#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
47cdf0e10cSrcweir#include <com/sun/star/awt/Size.hpp>
48cdf0e10cSrcweir#include <com/sun/star/accessibility/XAccessibleRelationSet.hpp>
49cdf0e10cSrcweir#include <com/sun/star/accessibility/AccessibleRelationType.hpp>
50cdf0e10cSrcweir#include <com/sun/star/lang/DisposedException.hpp>
51cdf0e10cSrcweir
52cdf0e10cSrcweirusing namespace ::com::sun::star::accessibility;
53cdf0e10cSrcweirusing namespace ::com::sun::star::awt;
54cdf0e10cSrcweirusing namespace ::com::sun::star::lang;
55cdf0e10cSrcweirusing namespace ::com::sun::star::uno;
56cdf0e10cSrcweir
57cdf0e10cSrcweir@interface SalFrameWindow : NSWindow
58cdf0e10cSrcweir{
59cdf0e10cSrcweir}
60cdf0e10cSrcweir-(Reference<XAccessibleContext>)accessibleContext;
61cdf0e10cSrcweir@end
62cdf0e10cSrcweir
63cdf0e10cSrcweirstatic BOOL isPopupMenuOpen = NO;
64cdf0e10cSrcweir
65cdf0e10cSrcweir@implementation AquaA11yWrapper : NSView
66cdf0e10cSrcweir
67cdf0e10cSrcweir#pragma mark -
68cdf0e10cSrcweir#pragma mark Init and dealloc
69cdf0e10cSrcweir
70cdf0e10cSrcweir-(id)initWithAccessibleContext: (Reference < XAccessibleContext >) rxAccessibleContext {
71cdf0e10cSrcweir    self = [ super init ];
72cdf0e10cSrcweir    if ( self != nil ) {
73cdf0e10cSrcweir        [ self setDefaults: rxAccessibleContext ];
74cdf0e10cSrcweir    }
75cdf0e10cSrcweir    return self;
76cdf0e10cSrcweir}
77cdf0e10cSrcweir
78cdf0e10cSrcweir-(void) setDefaults: (Reference < XAccessibleContext >) rxAccessibleContext {
79cdf0e10cSrcweir    mDefaultFontsize = 0.0;
80cdf0e10cSrcweir    mpDefaultFontname = nil;
81cdf0e10cSrcweir    mpReferenceWrapper = new ReferenceWrapper;
82cdf0e10cSrcweir    mActsAsRadioGroup = NO;
83cdf0e10cSrcweir    mpReferenceWrapper -> rAccessibleContext = rxAccessibleContext;
84cdf0e10cSrcweir    mIsTableCell = NO;
85cdf0e10cSrcweir    // Querying all supported interfaces
86cdf0e10cSrcweir    try {
87cdf0e10cSrcweir        // XAccessibleComponent
88cdf0e10cSrcweir        mpReferenceWrapper -> rAccessibleComponent = Reference < XAccessibleComponent > ( rxAccessibleContext, UNO_QUERY );
89cdf0e10cSrcweir        // XAccessibleExtendedComponent
90cdf0e10cSrcweir        mpReferenceWrapper -> rAccessibleExtendedComponent = Reference < XAccessibleExtendedComponent > ( rxAccessibleContext, UNO_QUERY );
91cdf0e10cSrcweir        // XAccessibleSelection
92cdf0e10cSrcweir        mpReferenceWrapper -> rAccessibleSelection = Reference< XAccessibleSelection > ( rxAccessibleContext, UNO_QUERY );
93cdf0e10cSrcweir        // XAccessibleTable
94cdf0e10cSrcweir        mpReferenceWrapper -> rAccessibleTable = Reference < XAccessibleTable > ( rxAccessibleContext, UNO_QUERY );
95cdf0e10cSrcweir        // XAccessibleText
96cdf0e10cSrcweir        mpReferenceWrapper -> rAccessibleText = Reference < XAccessibleText > ( rxAccessibleContext, UNO_QUERY );
97cdf0e10cSrcweir        // XAccessibleEditableText
98cdf0e10cSrcweir        mpReferenceWrapper -> rAccessibleEditableText = Reference < XAccessibleEditableText > ( rxAccessibleContext, UNO_QUERY );
99cdf0e10cSrcweir        // XAccessibleValue
100cdf0e10cSrcweir        mpReferenceWrapper -> rAccessibleValue = Reference < XAccessibleValue > ( rxAccessibleContext, UNO_QUERY );
101cdf0e10cSrcweir        // XAccessibleAction
102cdf0e10cSrcweir        mpReferenceWrapper -> rAccessibleAction = Reference < XAccessibleAction > ( rxAccessibleContext, UNO_QUERY );
103cdf0e10cSrcweir        // XAccessibleTextAttributes
104cdf0e10cSrcweir        mpReferenceWrapper -> rAccessibleTextAttributes = Reference < XAccessibleTextAttributes > ( rxAccessibleContext, UNO_QUERY );
105cdf0e10cSrcweir        // XAccessibleMultiLineText
106cdf0e10cSrcweir        mpReferenceWrapper -> rAccessibleMultiLineText = Reference < XAccessibleMultiLineText > ( rxAccessibleContext, UNO_QUERY );
107cdf0e10cSrcweir        // XAccessibleEventBroadcaster
108cdf0e10cSrcweir        #if 0
109cdf0e10cSrcweir        /* #i102033# NSAccessibility does not seemt to know an equivalent for transient children.
110cdf0e10cSrcweir           That means we need to cache this, else e.g. tree list boxes are not accessible (moreover
111cdf0e10cSrcweir           it crashes by notifying dead objects - which would seemt o be another bug)
112cdf0e10cSrcweir
113cdf0e10cSrcweir           FIXME:
114cdf0e10cSrcweir           Unfortunately this can increase memory consumption drastically until the non transient parent
115cdf0e10cSrcweir           is destroyed an finally all the transients are released.
116cdf0e10cSrcweir        */
117cdf0e10cSrcweir        if ( ! rxAccessibleContext -> getAccessibleStateSet() -> contains ( AccessibleStateType::TRANSIENT ) )
118cdf0e10cSrcweir        #endif
119cdf0e10cSrcweir        {
120cdf0e10cSrcweir            Reference< XAccessibleEventBroadcaster > xBroadcaster(rxAccessibleContext, UNO_QUERY);
121cdf0e10cSrcweir            if( xBroadcaster.is() ) {
122cdf0e10cSrcweir                /*
123cdf0e10cSrcweir                 * We intentionally do not hold a reference to the event listener in the wrapper object,
124cdf0e10cSrcweir                 * but let the listener control the life cycle of the wrapper instead ..
125cdf0e10cSrcweir                 */
126cdf0e10cSrcweir                xBroadcaster->addEventListener( new AquaA11yEventListener( self, rxAccessibleContext -> getAccessibleRole() ) );
127cdf0e10cSrcweir            }
128cdf0e10cSrcweir        }
129cdf0e10cSrcweir        // TABLE_CELL
130cdf0e10cSrcweir        if ( rxAccessibleContext -> getAccessibleRole() == AccessibleRole::TABLE_CELL ) {
131cdf0e10cSrcweir            mIsTableCell = YES;
132cdf0e10cSrcweir        }
133cdf0e10cSrcweir    } catch ( const Exception ) {
134cdf0e10cSrcweir    }
135cdf0e10cSrcweir}
136cdf0e10cSrcweir
137cdf0e10cSrcweir-(void)dealloc {
138cdf0e10cSrcweir    if ( mpReferenceWrapper != nil ) {
139cdf0e10cSrcweir        delete mpReferenceWrapper;
140cdf0e10cSrcweir    }
141cdf0e10cSrcweir    if ( mpDefaultFontname != nil ) {
142cdf0e10cSrcweir        [ mpDefaultFontname release ];
143cdf0e10cSrcweir    }
144cdf0e10cSrcweir    [ super dealloc ];
145cdf0e10cSrcweir}
146cdf0e10cSrcweir
147cdf0e10cSrcweir#pragma mark -
148cdf0e10cSrcweir#pragma mark Utility Section
149cdf0e10cSrcweir
150cdf0e10cSrcweir// generates selectors for attribute name AXAttributeNameHere
151cdf0e10cSrcweir// (getter without parameter) attributeNameHereAttribute
152cdf0e10cSrcweir// (getter with parameter)    attributeNameHereAttributeForParameter:
153cdf0e10cSrcweir// (setter)                   setAttributeNameHereAttributeForElement:to:
154cdf0e10cSrcweir-(SEL)selectorForAttribute:(NSString *)attribute asGetter:(BOOL)asGetter withGetterParameter:(BOOL)withGetterParameter {
155cdf0e10cSrcweir    SEL selector = nil;
156cdf0e10cSrcweir    NSAutoreleasePool * pool = [ [ NSAutoreleasePool alloc ] init ];
157cdf0e10cSrcweir    @try {
158cdf0e10cSrcweir        // step 1: create method name from attribute name
159cdf0e10cSrcweir        NSMutableString * methodName = [ NSMutableString string ];
160cdf0e10cSrcweir        if ( ! asGetter ) {
161cdf0e10cSrcweir            [ methodName appendString: @"set" ];
162cdf0e10cSrcweir        }
163cdf0e10cSrcweir        NSRange aRange = { 2, 1 };
164cdf0e10cSrcweir        NSString * firstChar = [ attribute substringWithRange: aRange ]; // drop leading "AX" and get first char
165cdf0e10cSrcweir        if ( asGetter ) {
166cdf0e10cSrcweir            [ methodName appendString: [ firstChar lowercaseString ] ];
167cdf0e10cSrcweir        } else {
168cdf0e10cSrcweir            [ methodName appendString: firstChar ];
169cdf0e10cSrcweir        }
170cdf0e10cSrcweir        [ methodName appendString: [ attribute substringFromIndex: 3 ] ]; // append rest of attribute name
171cdf0e10cSrcweir        // append rest of method name
172cdf0e10cSrcweir        [ methodName appendString: @"Attribute" ];
173cdf0e10cSrcweir        if ( ! asGetter ) {
174cdf0e10cSrcweir            [ methodName appendString: @"ForElement:to:" ];
175cdf0e10cSrcweir        } else if ( asGetter && withGetterParameter ) {
176cdf0e10cSrcweir            [ methodName appendString: @"ForParameter:" ];
177cdf0e10cSrcweir        }
178cdf0e10cSrcweir        // step 2: create selector
179cdf0e10cSrcweir        selector = NSSelectorFromString ( methodName );
180cdf0e10cSrcweir    } @catch ( id exception ) {
181cdf0e10cSrcweir        selector = nil;
182cdf0e10cSrcweir    }
183cdf0e10cSrcweir    [ pool release ];
184cdf0e10cSrcweir    return selector;
185cdf0e10cSrcweir}
186cdf0e10cSrcweir
187cdf0e10cSrcweir-(Reference < XAccessible >)getFirstRadioButtonInGroup {
188cdf0e10cSrcweir    Reference < XAccessibleRelationSet > rxAccessibleRelationSet = [ self accessibleContext ] -> getAccessibleRelationSet();
189cdf0e10cSrcweir    if( rxAccessibleRelationSet.is() )
190cdf0e10cSrcweir    {
191cdf0e10cSrcweir        AccessibleRelation relationMemberOf = rxAccessibleRelationSet -> getRelationByType ( AccessibleRelationType::MEMBER_OF );
192cdf0e10cSrcweir        if ( relationMemberOf.RelationType == AccessibleRelationType::MEMBER_OF && relationMemberOf.TargetSet.hasElements() )
193cdf0e10cSrcweir            return Reference < XAccessible > ( relationMemberOf.TargetSet[0], UNO_QUERY );
194cdf0e10cSrcweir    }
195cdf0e10cSrcweir    return Reference < XAccessible > ();
196cdf0e10cSrcweir}
197cdf0e10cSrcweir
198cdf0e10cSrcweir-(BOOL)isFirstRadioButtonInGroup {
199cdf0e10cSrcweir    Reference < XAccessible > rFirstMateAccessible = [ self getFirstRadioButtonInGroup ];
200cdf0e10cSrcweir    if ( rFirstMateAccessible.is() && rFirstMateAccessible -> getAccessibleContext().get() == [ self accessibleContext ] ) {
201cdf0e10cSrcweir        return YES;
202cdf0e10cSrcweir    }
203cdf0e10cSrcweir    return NO;
204cdf0e10cSrcweir}
205cdf0e10cSrcweir
206cdf0e10cSrcweir#pragma mark -
207cdf0e10cSrcweir#pragma mark Attribute Value Getters
208cdf0e10cSrcweir// ( called via Reflection by accessibilityAttributeValue )
209cdf0e10cSrcweir
210cdf0e10cSrcweir/*
211cdf0e10cSrcweir    Radiobutton grouping is done differently in NSAccessibility and the UNO-API. In UNO related radio buttons share an entry in their
212cdf0e10cSrcweir    RelationSet. In NSAccessibility the relationship is axpressed through the hierarchy. A AXRadioGroup contains two or more AXRadioButton
213cdf0e10cSrcweir    objects. Since this group is not available in the UNO hierarchy, an extra wrapper is used for it. This wrapper shares almost all
214cdf0e10cSrcweir    attributes with the first radio button of the group, except for the role, subrole, role description, parent and children attributes.
215cdf0e10cSrcweir    So in this five methods there is a special treatment for radio buttons and groups.
216cdf0e10cSrcweir*/
217cdf0e10cSrcweir
218cdf0e10cSrcweir-(id)roleAttribute {
219cdf0e10cSrcweir    if ( mActsAsRadioGroup ) {
220cdf0e10cSrcweir        return NSAccessibilityRadioGroupRole;
221cdf0e10cSrcweir    }
222cdf0e10cSrcweir    else {
223cdf0e10cSrcweir        return [ AquaA11yRoleHelper getNativeRoleFrom: [ self accessibleContext ] ];
224cdf0e10cSrcweir    }
225cdf0e10cSrcweir}
226cdf0e10cSrcweir
227cdf0e10cSrcweir-(id)subroleAttribute {
228cdf0e10cSrcweir    if ( mActsAsRadioGroup ) {
229cdf0e10cSrcweir        return @"";
230cdf0e10cSrcweir    } else {
231cdf0e10cSrcweir        NSString * subRole = [ AquaA11yRoleHelper getNativeSubroleFrom: [ self accessibleContext ] -> getAccessibleRole() ];
232cdf0e10cSrcweir        if ( ! [ subRole isEqualToString: @"" ] ) {
233cdf0e10cSrcweir            return subRole;
234cdf0e10cSrcweir        } else {
235cdf0e10cSrcweir            [ subRole release ];
236cdf0e10cSrcweir            return [ super accessibilityAttributeValue: NSAccessibilitySubroleAttribute ];
237cdf0e10cSrcweir        }
238cdf0e10cSrcweir    }
239cdf0e10cSrcweir}
240cdf0e10cSrcweir
241cdf0e10cSrcweir-(id)titleAttribute {
242cdf0e10cSrcweir    return CreateNSString ( [ self accessibleContext ] -> getAccessibleName() );
243cdf0e10cSrcweir}
244cdf0e10cSrcweir
245cdf0e10cSrcweir-(id)descriptionAttribute {
246cdf0e10cSrcweir    if ( [ self accessibleContext ] -> getAccessibleRole() == AccessibleRole::COMBO_BOX ) {
247cdf0e10cSrcweir        return [ self titleAttribute ];
248cdf0e10cSrcweir    } else if ( [ self accessibleExtendedComponent ] != nil ) {
249cdf0e10cSrcweir        return [ AquaA11yComponentWrapper descriptionAttributeForElement: self ];
250cdf0e10cSrcweir    } else {
251cdf0e10cSrcweir        return CreateNSString ( [ self accessibleContext ] -> getAccessibleDescription() );
252cdf0e10cSrcweir    }
253cdf0e10cSrcweir}
254cdf0e10cSrcweir
255cdf0e10cSrcweir-(id)enabledAttribute {
256cdf0e10cSrcweir    if ( [ self accessibleContext ] -> getAccessibleStateSet().is() ) {
257cdf0e10cSrcweir        return [ NSNumber numberWithBool: [ self accessibleContext ] -> getAccessibleStateSet() -> contains ( AccessibleStateType::ENABLED ) ];
258cdf0e10cSrcweir    } else {
259cdf0e10cSrcweir        return nil;
260cdf0e10cSrcweir    }
261cdf0e10cSrcweir}
262cdf0e10cSrcweir
263cdf0e10cSrcweir-(id)focusedAttribute {
264cdf0e10cSrcweir    if ( [ self accessibleContext ] -> getAccessibleRole() == AccessibleRole::COMBO_BOX ) {
265cdf0e10cSrcweir        id isFocused = nil;
266cdf0e10cSrcweir        Reference < XAccessible > rxParent = [ self accessibleContext ] -> getAccessibleParent();
267cdf0e10cSrcweir        if ( rxParent.is() ) {
268cdf0e10cSrcweir            Reference < XAccessibleContext > rxContext = rxParent -> getAccessibleContext();
269cdf0e10cSrcweir            if ( rxContext.is() && rxContext -> getAccessibleStateSet().is() ) {
270cdf0e10cSrcweir                isFocused = [ NSNumber numberWithBool: rxContext -> getAccessibleStateSet() -> contains ( AccessibleStateType::FOCUSED ) ];
271cdf0e10cSrcweir            }
272cdf0e10cSrcweir        }
273cdf0e10cSrcweir        return isFocused;
274cdf0e10cSrcweir    } else if ( [ self accessibleContext ] -> getAccessibleStateSet().is() ) {
275cdf0e10cSrcweir        return [ NSNumber numberWithBool: [ self accessibleContext ] -> getAccessibleStateSet() -> contains ( AccessibleStateType::FOCUSED ) ];
276cdf0e10cSrcweir    } else {
277cdf0e10cSrcweir        return nil;
278cdf0e10cSrcweir    }
279cdf0e10cSrcweir}
280cdf0e10cSrcweir
281cdf0e10cSrcweir-(id)parentAttribute {
282cdf0e10cSrcweir    if ( [ self accessibleContext ] -> getAccessibleRole() == AccessibleRole::RADIO_BUTTON && ! mActsAsRadioGroup ) {
283cdf0e10cSrcweir        Reference < XAccessible > rxAccessible = [ self getFirstRadioButtonInGroup ];
284cdf0e10cSrcweir        if ( rxAccessible.is() && rxAccessible -> getAccessibleContext().is() ) {
285cdf0e10cSrcweir            Reference < XAccessibleContext > rxAccessibleContext = rxAccessible -> getAccessibleContext();
286cdf0e10cSrcweir            id parent_wrapper = [ AquaA11yFactory wrapperForAccessibleContext: rxAccessibleContext createIfNotExists: YES asRadioGroup: YES ];
287cdf0e10cSrcweir            [ parent_wrapper autorelease ];
288cdf0e10cSrcweir            return NSAccessibilityUnignoredAncestor( parent_wrapper );
289cdf0e10cSrcweir        }
290cdf0e10cSrcweir        return nil;
291cdf0e10cSrcweir    }
292cdf0e10cSrcweir    try {
293cdf0e10cSrcweir        Reference< XAccessible > xParent( [ self accessibleContext ] -> getAccessibleParent() );
294cdf0e10cSrcweir        if ( xParent.is() ) {
295cdf0e10cSrcweir            Reference< XAccessibleContext > xContext( xParent -> getAccessibleContext() );
296cdf0e10cSrcweir            if ( xContext.is() ) {
297cdf0e10cSrcweir                id parent_wrapper = [ AquaA11yFactory wrapperForAccessibleContext: xContext ];
298cdf0e10cSrcweir                [ parent_wrapper autorelease ];
299cdf0e10cSrcweir                return NSAccessibilityUnignoredAncestor( parent_wrapper );
300cdf0e10cSrcweir            }
301cdf0e10cSrcweir        }
302cdf0e10cSrcweir    } catch (const Exception&) {
303cdf0e10cSrcweir    }
304cdf0e10cSrcweir
305cdf0e10cSrcweir    OSL_ASSERT( 0 );
306cdf0e10cSrcweir    return nil;
307cdf0e10cSrcweir}
308cdf0e10cSrcweir
309cdf0e10cSrcweir-(id)childrenAttribute {
310cdf0e10cSrcweir    if ( mActsAsRadioGroup ) {
311cdf0e10cSrcweir        NSMutableArray * children = [ [ NSMutableArray alloc ] init ];
312cdf0e10cSrcweir        Reference < XAccessibleRelationSet > rxAccessibleRelationSet = [ self accessibleContext ] -> getAccessibleRelationSet();
313cdf0e10cSrcweir        AccessibleRelation relationMemberOf = rxAccessibleRelationSet -> getRelationByType ( AccessibleRelationType::MEMBER_OF );
314cdf0e10cSrcweir        if ( relationMemberOf.RelationType == AccessibleRelationType::MEMBER_OF && relationMemberOf.TargetSet.hasElements() ) {
315cdf0e10cSrcweir            for ( int index = 0; index < relationMemberOf.TargetSet.getLength(); index++ ) {
316cdf0e10cSrcweir                Reference < XAccessible > rMateAccessible = Reference < XAccessible > ( relationMemberOf.TargetSet[index], UNO_QUERY );
317cdf0e10cSrcweir                if ( rMateAccessible.is() ) {
318cdf0e10cSrcweir                    Reference< XAccessibleContext > rMateAccessibleContext( rMateAccessible -> getAccessibleContext() );
319cdf0e10cSrcweir                    if ( rMateAccessibleContext.is() ) {
320cdf0e10cSrcweir                        id wrapper = [ AquaA11yFactory wrapperForAccessibleContext: rMateAccessibleContext ];
321cdf0e10cSrcweir                        [ children addObject: wrapper ];
322cdf0e10cSrcweir                        [ wrapper release ];
323cdf0e10cSrcweir                    }
324cdf0e10cSrcweir                }
325cdf0e10cSrcweir            }
326cdf0e10cSrcweir        }
327cdf0e10cSrcweir        return children;
328cdf0e10cSrcweir    } else if ( [ self accessibleTable ] != nil )
329cdf0e10cSrcweir    {
330cdf0e10cSrcweir        AquaA11yTableWrapper* pTable = [self isKindOfClass: [AquaA11yTableWrapper class]] ? (AquaA11yTableWrapper*)self : nil;
331cdf0e10cSrcweir        return [ AquaA11yTableWrapper childrenAttributeForElement: pTable ];
332cdf0e10cSrcweir    } else {
333cdf0e10cSrcweir        try {
334cdf0e10cSrcweir            NSMutableArray * children = [ [ NSMutableArray alloc ] init ];
335cdf0e10cSrcweir            Reference< XAccessibleContext > xContext( [ self accessibleContext ] );
336cdf0e10cSrcweir
337cdf0e10cSrcweir            sal_Int32 cnt = xContext -> getAccessibleChildCount();
338cdf0e10cSrcweir            for ( sal_Int32 i = 0; i < cnt; i++ ) {
339cdf0e10cSrcweir                Reference< XAccessible > xChild( xContext -> getAccessibleChild( i ) );
340cdf0e10cSrcweir                if( xChild.is() ) {
341cdf0e10cSrcweir                    Reference< XAccessibleContext > xChildContext( xChild -> getAccessibleContext() );
342cdf0e10cSrcweir                    // the menubar is already accessible (including Apple- and Application-Menu) through NSApplication => omit it here
343cdf0e10cSrcweir                    if ( xChildContext.is() && AccessibleRole::MENU_BAR != xChildContext -> getAccessibleRole() ) {
344cdf0e10cSrcweir                        id wrapper = [ AquaA11yFactory wrapperForAccessibleContext: xChildContext ];
345cdf0e10cSrcweir                        [ children addObject: wrapper ];
346cdf0e10cSrcweir                        [ wrapper release ];
347cdf0e10cSrcweir                    }
348cdf0e10cSrcweir                }
349cdf0e10cSrcweir            }
350cdf0e10cSrcweir
351cdf0e10cSrcweir            // if not already acting as RadioGroup now is the time to replace RadioButtons with RadioGroups and remove RadioButtons
352cdf0e10cSrcweir            if ( ! mActsAsRadioGroup ) {
353cdf0e10cSrcweir                NSEnumerator * enumerator = [ children objectEnumerator ];
354cdf0e10cSrcweir                AquaA11yWrapper * element;
355cdf0e10cSrcweir                while ( ( element = ( (AquaA11yWrapper *) [ enumerator nextObject ] ) ) ) {
356cdf0e10cSrcweir                    if ( [ element accessibleContext ] -> getAccessibleRole() == AccessibleRole::RADIO_BUTTON ) {
357cdf0e10cSrcweir                        if ( [ element isFirstRadioButtonInGroup ] ) {
358cdf0e10cSrcweir                            id wrapper = [ AquaA11yFactory wrapperForAccessibleContext: [ element accessibleContext ] createIfNotExists: YES asRadioGroup: YES ];
359cdf0e10cSrcweir                            [ children replaceObjectAtIndex: [ children indexOfObjectIdenticalTo: element ] withObject: wrapper ];
360cdf0e10cSrcweir                        }
361cdf0e10cSrcweir                        [ children removeObject: element ];
362cdf0e10cSrcweir                    }
363cdf0e10cSrcweir                }
364cdf0e10cSrcweir            }
365cdf0e10cSrcweir
366cdf0e10cSrcweir            [ children autorelease ];
367cdf0e10cSrcweir            return NSAccessibilityUnignoredChildren( children );
368cdf0e10cSrcweir        } catch (const Exception &e) {
369cdf0e10cSrcweir            // TODO: Log
370cdf0e10cSrcweir            return nil;
371cdf0e10cSrcweir        }
372cdf0e10cSrcweir    }
373cdf0e10cSrcweir}
374cdf0e10cSrcweir
375cdf0e10cSrcweir-(id)windowAttribute {
376cdf0e10cSrcweir    // go upstairs until reaching the broken connection
377cdf0e10cSrcweir    AquaA11yWrapper * aWrapper = self;
378cdf0e10cSrcweir    while ( [ aWrapper accessibleContext ] -> getAccessibleParent().is() ) {
379cdf0e10cSrcweir        aWrapper = [ AquaA11yFactory wrapperForAccessibleContext: [ aWrapper accessibleContext ] -> getAccessibleParent() -> getAccessibleContext() ];
380cdf0e10cSrcweir        [ aWrapper autorelease ];
381cdf0e10cSrcweir    }
382cdf0e10cSrcweir    // get associated NSWindow
38397dacec1SHerbert Dürr    NSWindow* theWindow = [ aWrapper windowForParent ];
38497dacec1SHerbert Dürr    return theWindow;
385cdf0e10cSrcweir}
386cdf0e10cSrcweir
387cdf0e10cSrcweir-(id)topLevelUIElementAttribute {
388cdf0e10cSrcweir    return [ self windowAttribute ];
389cdf0e10cSrcweir}
390cdf0e10cSrcweir
391cdf0e10cSrcweir-(id)sizeAttribute {
392cdf0e10cSrcweir    if ( [ self accessibleComponent ] != nil ) {
393cdf0e10cSrcweir        return [ AquaA11yComponentWrapper sizeAttributeForElement: self ];
394cdf0e10cSrcweir    } else {
395cdf0e10cSrcweir        return nil;
396cdf0e10cSrcweir    }
397cdf0e10cSrcweir}
398cdf0e10cSrcweir
399cdf0e10cSrcweir-(id)positionAttribute {
400cdf0e10cSrcweir    if ( [ self accessibleComponent ] != nil ) {
401cdf0e10cSrcweir        return [ AquaA11yComponentWrapper positionAttributeForElement: self ];
402cdf0e10cSrcweir    } else {
403cdf0e10cSrcweir        return nil;
404cdf0e10cSrcweir    }
405cdf0e10cSrcweir}
406cdf0e10cSrcweir
407cdf0e10cSrcweir-(id)helpAttribute {
408cdf0e10cSrcweir    return CreateNSString ( [ self accessibleContext ] -> getAccessibleDescription() );
409cdf0e10cSrcweir}
410cdf0e10cSrcweir
411cdf0e10cSrcweir-(id)roleDescriptionAttribute {
412cdf0e10cSrcweir    if ( mActsAsRadioGroup ) {
413cdf0e10cSrcweir        return [ AquaA11yRoleHelper getRoleDescriptionFrom: NSAccessibilityRadioGroupRole with: @"" ];
414cdf0e10cSrcweir	} else if( [ self accessibleContext ] -> getAccessibleRole() == AccessibleRole::RADIO_BUTTON ) {
415cdf0e10cSrcweir		// FIXME: VO should read this because of hierarchy, this is just a workaround
416cdf0e10cSrcweir		// get parent and its children
417cdf0e10cSrcweir		AquaA11yWrapper * parent = [ self parentAttribute ];
418cdf0e10cSrcweir		NSArray * children = [ parent childrenAttribute ];
419cdf0e10cSrcweir		// find index of self
420cdf0e10cSrcweir		int index = 1;
421cdf0e10cSrcweir		NSEnumerator * enumerator = [ children objectEnumerator ];
422cdf0e10cSrcweir		AquaA11yWrapper * child = nil;
423cdf0e10cSrcweir		while ( ( child = [ enumerator nextObject ] ) ) {
424cdf0e10cSrcweir			if ( self == child ) {
425cdf0e10cSrcweir				break;
426cdf0e10cSrcweir			}
427cdf0e10cSrcweir			index++;
428cdf0e10cSrcweir		}
429cdf0e10cSrcweir		// build string
430cdf0e10cSrcweir		NSNumber * nIndex = [ NSNumber numberWithInt: index ];
431cdf0e10cSrcweir		NSNumber * nGroupsize = [ NSNumber numberWithInt: [ children count ] ];
432cdf0e10cSrcweir		NSMutableString * value = [ [ NSMutableString alloc ] init ];
433cdf0e10cSrcweir		[ value appendString: @"radio button " ];
434cdf0e10cSrcweir		[ value appendString: [ nIndex stringValue ] ];
435cdf0e10cSrcweir		[ value appendString: @" of " ];
436cdf0e10cSrcweir		[ value appendString: [ nGroupsize stringValue ] ];
437cdf0e10cSrcweir		// clean up and return string
438cdf0e10cSrcweir		[ nIndex release ];
439cdf0e10cSrcweir		[ nGroupsize release ];
440cdf0e10cSrcweir		[ children release ];
441cdf0e10cSrcweir		return value;
442cdf0e10cSrcweir    } else {
443cdf0e10cSrcweir        return [ AquaA11yRoleHelper getRoleDescriptionFrom:
444cdf0e10cSrcweir                [ AquaA11yRoleHelper getNativeRoleFrom: [ self accessibleContext ] ]
445cdf0e10cSrcweir                with: [ AquaA11yRoleHelper getNativeSubroleFrom: [ self accessibleContext ] -> getAccessibleRole() ] ];
446cdf0e10cSrcweir    }
447cdf0e10cSrcweir}
448cdf0e10cSrcweir
449cdf0e10cSrcweir-(id)valueAttribute {
450cdf0e10cSrcweir    if ( [ [ self roleAttribute ] isEqualToString: NSAccessibilityMenuItemRole ] ) {
451cdf0e10cSrcweir        return nil;
452cdf0e10cSrcweir    } else if ( [ self accessibleText ] != nil ) {
453cdf0e10cSrcweir        return [ AquaA11yTextWrapper valueAttributeForElement: self ];
454cdf0e10cSrcweir    } else if ( [ self accessibleValue ] != nil ) {
455cdf0e10cSrcweir        return [ AquaA11yValueWrapper valueAttributeForElement: self ];
456cdf0e10cSrcweir    } else {
457cdf0e10cSrcweir        return nil;
458cdf0e10cSrcweir    }
459cdf0e10cSrcweir}
460cdf0e10cSrcweir
461cdf0e10cSrcweir-(id)minValueAttribute {
462cdf0e10cSrcweir    if ( [ self accessibleValue ] != nil ) {
463cdf0e10cSrcweir        return [ AquaA11yValueWrapper minValueAttributeForElement: self ];
464cdf0e10cSrcweir    } else {
465cdf0e10cSrcweir        return nil;
466cdf0e10cSrcweir    }
467cdf0e10cSrcweir}
468cdf0e10cSrcweir
469cdf0e10cSrcweir-(id)maxValueAttribute {
470cdf0e10cSrcweir    if ( [ self accessibleValue ] != nil ) {
471cdf0e10cSrcweir        return [ AquaA11yValueWrapper maxValueAttributeForElement: self ];
472cdf0e10cSrcweir    } else {
473cdf0e10cSrcweir        return nil;
474cdf0e10cSrcweir    }
475cdf0e10cSrcweir}
476cdf0e10cSrcweir
477cdf0e10cSrcweir-(id)contentsAttribute {
478cdf0e10cSrcweir    return [ self childrenAttribute ];
479cdf0e10cSrcweir}
480cdf0e10cSrcweir
481cdf0e10cSrcweir-(id)selectedChildrenAttribute {
482cdf0e10cSrcweir    return [ AquaA11ySelectionWrapper selectedChildrenAttributeForElement: self ];
483cdf0e10cSrcweir}
484cdf0e10cSrcweir
485cdf0e10cSrcweir-(id)numberOfCharactersAttribute {
486cdf0e10cSrcweir    if ( [ self accessibleText ] != nil ) {
487cdf0e10cSrcweir        return [ AquaA11yTextWrapper numberOfCharactersAttributeForElement: self ];
488cdf0e10cSrcweir    } else {
489cdf0e10cSrcweir        return nil;
490cdf0e10cSrcweir    }
491cdf0e10cSrcweir}
492cdf0e10cSrcweir
493cdf0e10cSrcweir-(id)selectedTextAttribute {
494cdf0e10cSrcweir    if ( [ self accessibleText ] != nil ) {
495cdf0e10cSrcweir        return [ AquaA11yTextWrapper selectedTextAttributeForElement: self ];
496cdf0e10cSrcweir    } else {
497cdf0e10cSrcweir        return nil;
498cdf0e10cSrcweir    }
499cdf0e10cSrcweir}
500cdf0e10cSrcweir
501cdf0e10cSrcweir-(id)selectedTextRangeAttribute {
502cdf0e10cSrcweir    if ( [ self accessibleText ] != nil ) {
503cdf0e10cSrcweir        return [ AquaA11yTextWrapper selectedTextRangeAttributeForElement: self ];
504cdf0e10cSrcweir    } else {
505cdf0e10cSrcweir        return nil;
506cdf0e10cSrcweir    }
507cdf0e10cSrcweir}
508cdf0e10cSrcweir
509cdf0e10cSrcweir-(id)visibleCharacterRangeAttribute {
510cdf0e10cSrcweir    if ( [ self accessibleText ] != nil ) {
511cdf0e10cSrcweir        return [ AquaA11yTextWrapper visibleCharacterRangeAttributeForElement: self ];
512cdf0e10cSrcweir    } else {
513cdf0e10cSrcweir        return nil;
514cdf0e10cSrcweir    }
515cdf0e10cSrcweir}
516cdf0e10cSrcweir
517cdf0e10cSrcweir-(id)tabsAttribute {
518cdf0e10cSrcweir    return self; // TODO ???
519cdf0e10cSrcweir}
520cdf0e10cSrcweir
521cdf0e10cSrcweir-(id)sharedTextUIElementsAttribute {
522cdf0e10cSrcweir    if ( [ self accessibleText ] != nil ) {
523cdf0e10cSrcweir        return [ AquaA11yTextWrapper sharedTextUIElementsAttributeForElement: self ];
524cdf0e10cSrcweir    } else {
525cdf0e10cSrcweir        return nil;
526cdf0e10cSrcweir    }
527cdf0e10cSrcweir}
528cdf0e10cSrcweir
529cdf0e10cSrcweir-(id)sharedCharacterRangeAttribute {
530cdf0e10cSrcweir    if ( [ self accessibleText ] != nil ) {
531cdf0e10cSrcweir        return [ AquaA11yTextWrapper sharedCharacterRangeAttributeForElement: self ];
532cdf0e10cSrcweir    } else {
533cdf0e10cSrcweir        return nil;
534cdf0e10cSrcweir    }
535cdf0e10cSrcweir}
536cdf0e10cSrcweir
537cdf0e10cSrcweir-(id)expandedAttribute {
538cdf0e10cSrcweir    return [ NSNumber numberWithBool: [ self accessibleContext ] -> getAccessibleStateSet() -> contains ( AccessibleStateType::EXPANDED ) ];
539cdf0e10cSrcweir}
540cdf0e10cSrcweir
541cdf0e10cSrcweir-(id)selectedAttribute {
542cdf0e10cSrcweir    return [ NSNumber numberWithBool: [ self accessibleContext ] -> getAccessibleStateSet() -> contains ( AccessibleStateType::SELECTED ) ];
543cdf0e10cSrcweir}
544cdf0e10cSrcweir
545cdf0e10cSrcweir-(id)stringForRangeAttributeForParameter:(id)range {
546cdf0e10cSrcweir    if ( [ self accessibleText ] != nil ) {
547cdf0e10cSrcweir        return [ AquaA11yTextWrapper stringForRangeAttributeForElement: self forParameter: range ];
548cdf0e10cSrcweir    } else {
549cdf0e10cSrcweir        return nil;
550cdf0e10cSrcweir    }
551cdf0e10cSrcweir}
552cdf0e10cSrcweir
553cdf0e10cSrcweir-(id)attributedStringForRangeAttributeForParameter:(id)range {
554cdf0e10cSrcweir    if ( [ self accessibleText ] != nil ) {
555cdf0e10cSrcweir        return [ AquaA11yTextWrapper attributedStringForRangeAttributeForElement: self forParameter: range ];
556cdf0e10cSrcweir    } else {
557cdf0e10cSrcweir        return nil;
558cdf0e10cSrcweir    }
559cdf0e10cSrcweir}
560cdf0e10cSrcweir
561cdf0e10cSrcweir-(id)rangeForIndexAttributeForParameter:(id)index {
562cdf0e10cSrcweir    if ( [ self accessibleText ] != nil ) {
563cdf0e10cSrcweir        return [ AquaA11yTextWrapper rangeForIndexAttributeForElement: self forParameter: index ];
564cdf0e10cSrcweir    } else {
565cdf0e10cSrcweir        return nil;
566cdf0e10cSrcweir    }
567cdf0e10cSrcweir}
568cdf0e10cSrcweir
569cdf0e10cSrcweir-(id)rangeForPositionAttributeForParameter:(id)point {
570cdf0e10cSrcweir    if ( [ self accessibleText ] != nil ) {
571cdf0e10cSrcweir        return [ AquaA11yTextWrapper rangeForPositionAttributeForElement: self forParameter: point ];
572cdf0e10cSrcweir    } else {
573cdf0e10cSrcweir        return nil;
574cdf0e10cSrcweir    }
575cdf0e10cSrcweir}
576cdf0e10cSrcweir
577cdf0e10cSrcweir-(id)boundsForRangeAttributeForParameter:(id)range {
578cdf0e10cSrcweir    if ( [ self accessibleText ] != nil ) {
579cdf0e10cSrcweir        return [ AquaA11yTextWrapper boundsForRangeAttributeForElement: self forParameter: range ];
580cdf0e10cSrcweir    } else {
581cdf0e10cSrcweir        return nil;
582cdf0e10cSrcweir    }
583cdf0e10cSrcweir}
584cdf0e10cSrcweir
585cdf0e10cSrcweir-(id)styleRangeForIndexAttributeForParameter:(id)index {
586cdf0e10cSrcweir    if ( [ self accessibleText ] != nil ) {
587cdf0e10cSrcweir        return [ AquaA11yTextWrapper styleRangeForIndexAttributeForElement: self forParameter: index ];
588cdf0e10cSrcweir    } else {
589cdf0e10cSrcweir        return nil;
590cdf0e10cSrcweir    }
591cdf0e10cSrcweir}
592cdf0e10cSrcweir
593cdf0e10cSrcweir-(id)rTFForRangeAttributeForParameter:(id)range {
594cdf0e10cSrcweir    if ( [ self accessibleText ] != nil ) {
595cdf0e10cSrcweir        return [ AquaA11yTextWrapper rTFForRangeAttributeForElement: self forParameter: range ];
596cdf0e10cSrcweir    } else {
597cdf0e10cSrcweir        return nil;
598cdf0e10cSrcweir    }
599cdf0e10cSrcweir}
600cdf0e10cSrcweir
601cdf0e10cSrcweir-(id)orientationAttribute {
602cdf0e10cSrcweir    NSString * orientation = nil;
603cdf0e10cSrcweir    Reference < XAccessibleStateSet > stateSet = [ self accessibleContext ] -> getAccessibleStateSet();
604cdf0e10cSrcweir    if ( stateSet -> contains ( AccessibleStateType::HORIZONTAL ) ) {
605cdf0e10cSrcweir        orientation = NSAccessibilityHorizontalOrientationValue;
606cdf0e10cSrcweir    } else if ( stateSet -> contains ( AccessibleStateType::VERTICAL ) ) {
607cdf0e10cSrcweir        orientation = NSAccessibilityVerticalOrientationValue;
608cdf0e10cSrcweir    }
609cdf0e10cSrcweir    return orientation;
610cdf0e10cSrcweir}
611cdf0e10cSrcweir
612cdf0e10cSrcweir-(id)titleUIElementAttribute {
613cdf0e10cSrcweir    if ( [ self accessibleContext ] -> getAccessibleRelationSet().is() ) {
614cdf0e10cSrcweir        NSString * title = [ self titleAttribute ];
615cdf0e10cSrcweir        id titleElement = nil;
616cdf0e10cSrcweir        if ( [ title length ] == 0 ) {
617cdf0e10cSrcweir            AccessibleRelation relationLabeledBy = [ self accessibleContext ] -> getAccessibleRelationSet() -> getRelationByType ( AccessibleRelationType::LABELED_BY );
618cdf0e10cSrcweir            if ( relationLabeledBy.RelationType == AccessibleRelationType::LABELED_BY && relationLabeledBy.TargetSet.hasElements()  ) {
619cdf0e10cSrcweir                Reference < XAccessible > rxAccessible ( relationLabeledBy.TargetSet[0], UNO_QUERY );
620cdf0e10cSrcweir                titleElement = [ AquaA11yFactory wrapperForAccessibleContext: rxAccessible -> getAccessibleContext() ];
621cdf0e10cSrcweir            }
622cdf0e10cSrcweir        }
623cdf0e10cSrcweir        if ( title != nil ) {
624cdf0e10cSrcweir            [ title release ];
625cdf0e10cSrcweir        }
626cdf0e10cSrcweir        return titleElement;
627cdf0e10cSrcweir    } else {
628cdf0e10cSrcweir        return nil;
629cdf0e10cSrcweir    }
630cdf0e10cSrcweir}
631cdf0e10cSrcweir
632cdf0e10cSrcweir-(id)servesAsTitleForUIElementsAttribute {
633cdf0e10cSrcweir    if ( [ self accessibleContext ] -> getAccessibleRelationSet().is() ) {
634cdf0e10cSrcweir        id titleForElement = nil;
635cdf0e10cSrcweir        AccessibleRelation relationLabelFor = [ self accessibleContext ] -> getAccessibleRelationSet() -> getRelationByType ( AccessibleRelationType::LABEL_FOR );
636cdf0e10cSrcweir        if ( relationLabelFor.RelationType == AccessibleRelationType::LABEL_FOR && relationLabelFor.TargetSet.hasElements() ) {
637cdf0e10cSrcweir            Reference < XAccessible > rxAccessible ( relationLabelFor.TargetSet[0], UNO_QUERY );
638cdf0e10cSrcweir            titleForElement = [ AquaA11yFactory wrapperForAccessibleContext: rxAccessible -> getAccessibleContext() ];
639cdf0e10cSrcweir        }
640cdf0e10cSrcweir        return titleForElement;
641cdf0e10cSrcweir    } else {
642cdf0e10cSrcweir        return nil;
643cdf0e10cSrcweir    }
644cdf0e10cSrcweir}
645cdf0e10cSrcweir
646cdf0e10cSrcweir-(id)lineForIndexAttributeForParameter:(id)index {
647cdf0e10cSrcweir    if ( [ self accessibleMultiLineText ] != nil ) {
648cdf0e10cSrcweir        return [ AquaA11yTextWrapper lineForIndexAttributeForElement: self forParameter: index ];
649cdf0e10cSrcweir    } else {
650cdf0e10cSrcweir        return nil;
651cdf0e10cSrcweir    }
652cdf0e10cSrcweir}
653cdf0e10cSrcweir
654cdf0e10cSrcweir-(id)rangeForLineAttributeForParameter:(id)line {
655cdf0e10cSrcweir    if ( [ self accessibleMultiLineText ] != nil ) {
656cdf0e10cSrcweir        return [ AquaA11yTextWrapper rangeForLineAttributeForElement: self forParameter: line ];
657cdf0e10cSrcweir    } else {
658cdf0e10cSrcweir        return nil;
659cdf0e10cSrcweir    }
660cdf0e10cSrcweir}
661cdf0e10cSrcweir
662cdf0e10cSrcweir#pragma mark -
663cdf0e10cSrcweir#pragma mark Accessibility Protocol
664cdf0e10cSrcweir
665cdf0e10cSrcweir-(id)accessibilityAttributeValue:(NSString *)attribute {
666cdf0e10cSrcweir    // #i90575# guard NSAccessibility protocol against unwanted access
667cdf0e10cSrcweir    if ( isPopupMenuOpen ) {
668cdf0e10cSrcweir        return nil;
669cdf0e10cSrcweir    }
670cdf0e10cSrcweir
671cdf0e10cSrcweir    id value = nil;
672cdf0e10cSrcweir    // if we are no longer in the wrapper repository, we have been disposed
673cdf0e10cSrcweir    AquaA11yWrapper * theWrapper = [ AquaA11yFactory wrapperForAccessibleContext: [ self accessibleContext ] createIfNotExists: NO ];
674cdf0e10cSrcweir    if ( theWrapper != nil || mIsTableCell ) {
675cdf0e10cSrcweir        try {
676cdf0e10cSrcweir            SEL methodSelector = [ self selectorForAttribute: attribute asGetter: YES withGetterParameter: NO ];
677cdf0e10cSrcweir            if ( [ self respondsToSelector: methodSelector ] ) {
678cdf0e10cSrcweir                value = [ self performSelector: methodSelector ];
679cdf0e10cSrcweir            }
680cdf0e10cSrcweir        } catch ( const DisposedException & e ) {
681cdf0e10cSrcweir            mIsTableCell = NO; // just to be sure
682cdf0e10cSrcweir            [ AquaA11yFactory removeFromWrapperRepositoryFor: [ self accessibleContext ] ];
683cdf0e10cSrcweir            return nil;
684cdf0e10cSrcweir        } catch ( const Exception & e ) {
685cdf0e10cSrcweir            // empty
686cdf0e10cSrcweir        }
687cdf0e10cSrcweir    }
688cdf0e10cSrcweir    if ( theWrapper != nil ) {
689cdf0e10cSrcweir        [ theWrapper release ]; // the above called method calls retain on the returned Wrapper
690cdf0e10cSrcweir    }
691cdf0e10cSrcweir    return value;
692cdf0e10cSrcweir}
693cdf0e10cSrcweir
694cdf0e10cSrcweir-(BOOL)accessibilityIsIgnored {
695cdf0e10cSrcweir    // #i90575# guard NSAccessibility protocol against unwanted access
696cdf0e10cSrcweir    if ( isPopupMenuOpen ) {
697*eae433d6SAndrea Pescetti        return FALSE;
698cdf0e10cSrcweir    }
699cdf0e10cSrcweir    BOOL ignored = NO;
700cdf0e10cSrcweir    sal_Int16 nRole = [ self accessibleContext ] -> getAccessibleRole();
701cdf0e10cSrcweir    switch ( nRole ) {
702cdf0e10cSrcweir        case AccessibleRole::PANEL:
703cdf0e10cSrcweir        case AccessibleRole::FRAME:
704cdf0e10cSrcweir        case AccessibleRole::ROOT_PANE:
705cdf0e10cSrcweir        case AccessibleRole::SEPARATOR:
706cdf0e10cSrcweir        case AccessibleRole::FILLER:
707cdf0e10cSrcweir        case AccessibleRole::DIALOG:
708cdf0e10cSrcweir            ignored = YES;
709cdf0e10cSrcweir            break;
710cdf0e10cSrcweir        default:
711cdf0e10cSrcweir            ignored = ! ( [ self accessibleContext ] -> getAccessibleStateSet() -> contains ( AccessibleStateType::VISIBLE ) );
712cdf0e10cSrcweir            break;
713cdf0e10cSrcweir    }
714cdf0e10cSrcweir    return ignored; // TODO: to be completed
715cdf0e10cSrcweir}
716cdf0e10cSrcweir
717cdf0e10cSrcweir-(NSArray *)accessibilityAttributeNames {
718cdf0e10cSrcweir    // #i90575# guard NSAccessibility protocol against unwanted access
719cdf0e10cSrcweir    if ( isPopupMenuOpen ) {
720cdf0e10cSrcweir        return nil;
721cdf0e10cSrcweir    }
722cdf0e10cSrcweir    NSString * nativeSubrole = nil;
723cdf0e10cSrcweir    NSString * title = nil;
724cdf0e10cSrcweir    NSMutableArray * attributeNames = nil;
725cdf0e10cSrcweir    sal_Int32 nAccessibleChildren = 0;
726cdf0e10cSrcweir    try {
727cdf0e10cSrcweir        // Default Attributes
728cdf0e10cSrcweir        attributeNames = [ NSMutableArray arrayWithObjects:
729cdf0e10cSrcweir            NSAccessibilityRoleAttribute,
730cdf0e10cSrcweir            NSAccessibilityDescriptionAttribute,
731cdf0e10cSrcweir            NSAccessibilityParentAttribute,
732cdf0e10cSrcweir            NSAccessibilityWindowAttribute,
733cdf0e10cSrcweir            NSAccessibilityHelpAttribute,
734cdf0e10cSrcweir            NSAccessibilityTopLevelUIElementAttribute,
735cdf0e10cSrcweir            NSAccessibilityRoleDescriptionAttribute,
736cdf0e10cSrcweir            nil ];
737cdf0e10cSrcweir        nativeSubrole = (NSString *) [ AquaA11yRoleHelper getNativeSubroleFrom: [ self accessibleContext ] -> getAccessibleRole() ];
738cdf0e10cSrcweir        title = (NSString *) [ self titleAttribute ];
739cdf0e10cSrcweir        Reference < XAccessibleRelationSet > rxRelationSet = [ self accessibleContext ] -> getAccessibleRelationSet();
740cdf0e10cSrcweir        // Special Attributes depending on attribute values
741cdf0e10cSrcweir        if ( nativeSubrole != nil && ! [ nativeSubrole isEqualToString: @"" ] ) {
742cdf0e10cSrcweir            [ attributeNames addObject: NSAccessibilitySubroleAttribute ];
743cdf0e10cSrcweir        }
744cdf0e10cSrcweir        try
745cdf0e10cSrcweir        {
746cdf0e10cSrcweir            nAccessibleChildren = [ self accessibleContext ] -> getAccessibleChildCount();
747cdf0e10cSrcweir            if (  nAccessibleChildren > 0 ) {
748cdf0e10cSrcweir                [ attributeNames addObject: NSAccessibilityChildrenAttribute ];
749cdf0e10cSrcweir        }
750cdf0e10cSrcweir        }
751cdf0e10cSrcweir        catch( DisposedException& ) {}
752cdf0e10cSrcweir        catch( RuntimeException& ) {}
753cdf0e10cSrcweir
754cdf0e10cSrcweir        if ( title != nil && ! [ title isEqualToString: @"" ] ) {
755cdf0e10cSrcweir            [ attributeNames addObject: NSAccessibilityTitleAttribute ];
756cdf0e10cSrcweir        }
757cdf0e10cSrcweir        if ( [ title length ] == 0 && rxRelationSet.is() && rxRelationSet -> containsRelation ( AccessibleRelationType::LABELED_BY ) ) {
758cdf0e10cSrcweir            [ attributeNames addObject: NSAccessibilityTitleUIElementAttribute ];
759cdf0e10cSrcweir        }
760cdf0e10cSrcweir        if ( rxRelationSet.is() && rxRelationSet -> containsRelation ( AccessibleRelationType::LABEL_FOR ) ) {
761cdf0e10cSrcweir            [ attributeNames addObject: NSAccessibilityServesAsTitleForUIElementsAttribute ];
762cdf0e10cSrcweir        }
763cdf0e10cSrcweir        // Special Attributes depending on interface
764cdf0e10cSrcweir        if( [self accessibleContext ] -> getAccessibleRole() == AccessibleRole::TABLE )
765cdf0e10cSrcweir            [AquaA11yTableWrapper addAttributeNamesTo: attributeNames object: self];
766cdf0e10cSrcweir
767cdf0e10cSrcweir        if ( [ self accessibleText ] != nil ) {
768cdf0e10cSrcweir            [ AquaA11yTextWrapper addAttributeNamesTo: attributeNames ];
769cdf0e10cSrcweir        }
770cdf0e10cSrcweir        if ( [ self accessibleComponent ] != nil ) {
771cdf0e10cSrcweir            [ AquaA11yComponentWrapper addAttributeNamesTo: attributeNames ];
772cdf0e10cSrcweir        }
773cdf0e10cSrcweir        if ( [ self accessibleSelection ] != nil ) {
774cdf0e10cSrcweir            [ AquaA11ySelectionWrapper addAttributeNamesTo: attributeNames ];
775cdf0e10cSrcweir        }
776cdf0e10cSrcweir        if ( [ self accessibleValue ] != nil ) {
777cdf0e10cSrcweir            [ AquaA11yValueWrapper addAttributeNamesTo: attributeNames ];
778cdf0e10cSrcweir        }
779cdf0e10cSrcweir        [ nativeSubrole release ];
780cdf0e10cSrcweir        [ title release ];
781cdf0e10cSrcweir        return attributeNames;
782cdf0e10cSrcweir    } catch ( DisposedException & e ) { // Object is no longer available
783cdf0e10cSrcweir        if ( nativeSubrole != nil ) {
784cdf0e10cSrcweir            [ nativeSubrole release ];
785cdf0e10cSrcweir        }
786cdf0e10cSrcweir        if ( title != nil ) {
787cdf0e10cSrcweir            [ title release ];
788cdf0e10cSrcweir        }
789cdf0e10cSrcweir        if ( attributeNames != nil ) {
790cdf0e10cSrcweir            [ attributeNames release ];
791cdf0e10cSrcweir        }
792cdf0e10cSrcweir        [ AquaA11yFactory removeFromWrapperRepositoryFor: [ self accessibleContext ] ];
793cdf0e10cSrcweir        return [ [ NSArray alloc ] init ];
794cdf0e10cSrcweir    }
795cdf0e10cSrcweir}
796cdf0e10cSrcweir
797cdf0e10cSrcweir-(BOOL)accessibilityIsAttributeSettable:(NSString *)attribute {
798cdf0e10cSrcweir    BOOL isSettable = NO;
799cdf0e10cSrcweir    if ( [ self accessibleText ] != nil ) {
800cdf0e10cSrcweir        isSettable = [ AquaA11yTextWrapper isAttributeSettable: attribute forElement: self ];
801cdf0e10cSrcweir    }
802cdf0e10cSrcweir    if ( ! isSettable && [ self accessibleComponent ] != nil ) {
803cdf0e10cSrcweir        isSettable = [ AquaA11yComponentWrapper isAttributeSettable: attribute forElement: self ];
804cdf0e10cSrcweir    }
805cdf0e10cSrcweir    if ( ! isSettable && [ self accessibleSelection ] != nil ) {
806cdf0e10cSrcweir        isSettable = [ AquaA11ySelectionWrapper isAttributeSettable: attribute forElement: self ];
807cdf0e10cSrcweir    }
808cdf0e10cSrcweir    if ( ! isSettable && [ self accessibleValue ] != nil ) {
809cdf0e10cSrcweir        isSettable = [ AquaA11yValueWrapper isAttributeSettable: attribute forElement: self ];
810cdf0e10cSrcweir    }
811cdf0e10cSrcweir    return isSettable; // TODO: to be completed
812cdf0e10cSrcweir}
813cdf0e10cSrcweir
814cdf0e10cSrcweir-(NSArray *)accessibilityParameterizedAttributeNames {
815cdf0e10cSrcweir    NSMutableArray * attributeNames = [ [ NSMutableArray alloc ] init ];
816cdf0e10cSrcweir    // Special Attributes depending on interface
817cdf0e10cSrcweir    if ( [ self accessibleText ] != nil ) {
818cdf0e10cSrcweir        [ AquaA11yTextWrapper addParameterizedAttributeNamesTo: attributeNames ];
819cdf0e10cSrcweir    }
820cdf0e10cSrcweir    return attributeNames; // TODO: to be completed
821cdf0e10cSrcweir}
822cdf0e10cSrcweir
823cdf0e10cSrcweir-(id)accessibilityAttributeValue:(NSString *)attribute forParameter:(id)parameter {
824cdf0e10cSrcweir    SEL methodSelector = [ self selectorForAttribute: attribute asGetter: YES withGetterParameter: YES ];
825cdf0e10cSrcweir    if ( [ self respondsToSelector: methodSelector ] ) {
826cdf0e10cSrcweir        return [ self performSelector: methodSelector withObject: parameter ];
827cdf0e10cSrcweir    }
828cdf0e10cSrcweir    return nil; // TODO: to be completed
829cdf0e10cSrcweir}
830cdf0e10cSrcweir
831cdf0e10cSrcweir-(BOOL)accessibilitySetOverrideValue:(id)value forAttribute:(NSString *)attribute
832cdf0e10cSrcweir{
833cdf0e10cSrcweir    (void)value;
834cdf0e10cSrcweir    (void)attribute;
835cdf0e10cSrcweir    return NO; // TODO
836cdf0e10cSrcweir}
837cdf0e10cSrcweir
838cdf0e10cSrcweir-(void)accessibilitySetValue:(id)value forAttribute:(NSString *)attribute {
839cdf0e10cSrcweir    SEL methodSelector = [ self selectorForAttribute: attribute asGetter: NO withGetterParameter: NO ];
840cdf0e10cSrcweir    if ( [ AquaA11yComponentWrapper respondsToSelector: methodSelector ] ) {
841cdf0e10cSrcweir        [ AquaA11yComponentWrapper performSelector: methodSelector withObject: self withObject: value ];
842cdf0e10cSrcweir    }
843cdf0e10cSrcweir    if ( [ AquaA11yTextWrapper respondsToSelector: methodSelector ] ) {
844cdf0e10cSrcweir        [ AquaA11yTextWrapper performSelector: methodSelector withObject: self withObject: value ];
845cdf0e10cSrcweir    }
846cdf0e10cSrcweir    if ( [ AquaA11ySelectionWrapper respondsToSelector: methodSelector ] ) {
847cdf0e10cSrcweir        [ AquaA11ySelectionWrapper performSelector: methodSelector withObject: self withObject: value ];
848cdf0e10cSrcweir    }
849cdf0e10cSrcweir    if ( [ AquaA11yValueWrapper respondsToSelector: methodSelector ] ) {
850cdf0e10cSrcweir        [ AquaA11yValueWrapper performSelector: methodSelector withObject: self withObject: value ];
851cdf0e10cSrcweir    }
852cdf0e10cSrcweir}
853cdf0e10cSrcweir
854cdf0e10cSrcweir-(id)accessibilityFocusedUIElement {
855cdf0e10cSrcweir    // #i90575# guard NSAccessibility protocol against unwanted access
856cdf0e10cSrcweir    if ( isPopupMenuOpen ) {
857cdf0e10cSrcweir        return nil;
858cdf0e10cSrcweir    }
859cdf0e10cSrcweir
860cdf0e10cSrcweir    // as this seems to be the first API call on a newly created SalFrameView object,
861cdf0e10cSrcweir    // make sure self gets registered in the repository ..
862cdf0e10cSrcweir    [ self accessibleContext ];
863cdf0e10cSrcweir
864cdf0e10cSrcweir    AquaA11yWrapper * focusedUIElement = AquaA11yFocusListener::get()->getFocusedUIElement();
865cdf0e10cSrcweir//    AquaA11yWrapper * ancestor = focusedUIElement;
866cdf0e10cSrcweir
867cdf0e10cSrcweir      // Make sure the focused object is a descendant of self
868cdf0e10cSrcweir//    do  {
869cdf0e10cSrcweir//       if( self == ancestor )
870cdf0e10cSrcweir             return focusedUIElement;
871cdf0e10cSrcweir
872cdf0e10cSrcweir//       ancestor = [ ancestor accessibilityAttributeValue: NSAccessibilityParentAttribute ];
873cdf0e10cSrcweir//    }  while( nil != ancestor );
874cdf0e10cSrcweir
875cdf0e10cSrcweir    return self;
876cdf0e10cSrcweir}
877cdf0e10cSrcweir
878cdf0e10cSrcweir// TODO: hard-coded like the role descriptions. is there a better way?
879cdf0e10cSrcweir-(NSString *)accessibilityActionDescription:(NSString *)action {
880cdf0e10cSrcweir    if ( [ action isEqualToString: NSAccessibilityConfirmAction ] ) {
881cdf0e10cSrcweir        return @"confirm";
882cdf0e10cSrcweir    } else if ( [ action isEqualToString: NSAccessibilityDecrementAction ] ) {
883cdf0e10cSrcweir        return @"decrement";
884cdf0e10cSrcweir    } else if ( [ action isEqualToString: NSAccessibilityDeleteAction ] ) {
885cdf0e10cSrcweir        return @"delete";
886cdf0e10cSrcweir    } else if ( [ action isEqualToString: NSAccessibilityIncrementAction ] ) {
887cdf0e10cSrcweir        return @"increment";
888cdf0e10cSrcweir    } else if ( [ action isEqualToString: NSAccessibilityPickAction ] ) {
889cdf0e10cSrcweir        return @"pick";
890cdf0e10cSrcweir    } else if ( [ action isEqualToString: NSAccessibilityPressAction ] ) {
891cdf0e10cSrcweir        return @"press";
892cdf0e10cSrcweir    } else if ( [ action isEqualToString: NSAccessibilityCancelAction ] ) {
893cdf0e10cSrcweir        return @"cancel";
894cdf0e10cSrcweir    } else if ( [ action isEqualToString: NSAccessibilityRaiseAction ] ) {
895cdf0e10cSrcweir        return @"raise";
896cdf0e10cSrcweir    } else if ( [ action isEqualToString: NSAccessibilityShowMenuAction ] ) {
897cdf0e10cSrcweir        return @"show menu";
898cdf0e10cSrcweir    } else {
899cdf0e10cSrcweir        return [ NSString string ];
900cdf0e10cSrcweir    }
901cdf0e10cSrcweir}
902cdf0e10cSrcweir
903cdf0e10cSrcweir-(AquaA11yWrapper *)actionResponder {
904cdf0e10cSrcweir    AquaA11yWrapper * wrapper = nil;
905cdf0e10cSrcweir    // get some information
906cdf0e10cSrcweir    NSString * role = (NSString *) [ self accessibilityAttributeValue: NSAccessibilityRoleAttribute ];
907cdf0e10cSrcweir    id enabledAttr = [ self enabledAttribute ];
908cdf0e10cSrcweir    BOOL enabled = [ enabledAttr boolValue ];
909cdf0e10cSrcweir    NSView * parent = (NSView *) [ self accessibilityAttributeValue: NSAccessibilityParentAttribute ];
910cdf0e10cSrcweir    AquaA11yWrapper * parentAsWrapper = nil;
911cdf0e10cSrcweir    if ( [ parent isKindOfClass: [ AquaA11yWrapper class ] ] ) {
912cdf0e10cSrcweir        parentAsWrapper = (AquaA11yWrapper *) parent;
913cdf0e10cSrcweir    }
914cdf0e10cSrcweir    NSString * parentRole = (NSString *) [ parent accessibilityAttributeValue: NSAccessibilityRoleAttribute ];
915cdf0e10cSrcweir    // if we are a textarea inside a combobox, then the combobox is the action responder
916cdf0e10cSrcweir    if ( enabled
917cdf0e10cSrcweir      && [ role isEqualToString: NSAccessibilityTextAreaRole ]
918cdf0e10cSrcweir      && [ parentRole isEqualToString: NSAccessibilityComboBoxRole ]
919cdf0e10cSrcweir      && parentAsWrapper != nil ) {
920cdf0e10cSrcweir        wrapper = parentAsWrapper;
921cdf0e10cSrcweir    } else if ( enabled && [ self accessibleAction ] != nil ) {
922cdf0e10cSrcweir        wrapper = self ;
923cdf0e10cSrcweir    }
924cdf0e10cSrcweir    [ parentRole release ];
925cdf0e10cSrcweir    [ enabledAttr release ];
926cdf0e10cSrcweir    [ role release ];
927cdf0e10cSrcweir    return wrapper;
928cdf0e10cSrcweir}
929cdf0e10cSrcweir
930cdf0e10cSrcweir-(void)accessibilityPerformAction:(NSString *)action {
931cdf0e10cSrcweir    AquaA11yWrapper * actionResponder = [ self actionResponder ];
932cdf0e10cSrcweir    if ( actionResponder != nil ) {
933cdf0e10cSrcweir        [ AquaA11yActionWrapper doAction: action ofElement: actionResponder ];
934cdf0e10cSrcweir    }
935cdf0e10cSrcweir}
936cdf0e10cSrcweir
937cdf0e10cSrcweir-(NSArray *)accessibilityActionNames {
938cdf0e10cSrcweir    NSArray * actionNames = nil;
939cdf0e10cSrcweir    AquaA11yWrapper * actionResponder = [ self actionResponder ];
940cdf0e10cSrcweir    if ( actionResponder != nil ) {
941cdf0e10cSrcweir        actionNames = [ AquaA11yActionWrapper actionNamesForElement: actionResponder ];
942cdf0e10cSrcweir    } else {
943cdf0e10cSrcweir        actionNames = [ [ NSArray alloc ] init ];
944cdf0e10cSrcweir    }
945cdf0e10cSrcweir    return actionNames;
946cdf0e10cSrcweir}
947cdf0e10cSrcweir
948cdf0e10cSrcweir#pragma mark -
949cdf0e10cSrcweir#pragma mark Hit Test
950cdf0e10cSrcweir
951cdf0e10cSrcweir-(BOOL)isViewElement:(NSObject *)viewElement hitByPoint:(NSPoint)point {
952cdf0e10cSrcweir    BOOL hit = NO;
953cdf0e10cSrcweir    NSAutoreleasePool * pool = [ [ NSAutoreleasePool alloc ] init ];
954cdf0e10cSrcweir    NSValue * position = [ viewElement accessibilityAttributeValue: NSAccessibilityPositionAttribute ];
955cdf0e10cSrcweir    NSValue * size = [ viewElement accessibilityAttributeValue: NSAccessibilitySizeAttribute ];
956cdf0e10cSrcweir    if ( position != nil && size != nil ) {
957cdf0e10cSrcweir        float minX = [ position pointValue ].x;
958cdf0e10cSrcweir        float minY = [ position pointValue ].y;
959cdf0e10cSrcweir        float maxX = minX + [ size sizeValue ].width;
960cdf0e10cSrcweir        float maxY = minY + [ size sizeValue ].height;
961cdf0e10cSrcweir        if ( minX < point.x && maxX > point.x && minY < point.y && maxY > point.y ) {
962cdf0e10cSrcweir            hit = YES;
963cdf0e10cSrcweir        }
964cdf0e10cSrcweir    }
965cdf0e10cSrcweir    [ pool release ];
966cdf0e10cSrcweir    return hit;
967cdf0e10cSrcweir}
968cdf0e10cSrcweir
969cdf0e10cSrcweirReference < XAccessibleContext > hitTestRunner ( com::sun::star::awt::Point point,
970cdf0e10cSrcweir                                                 Reference < XAccessibleContext > rxAccessibleContext ) {
971cdf0e10cSrcweir    Reference < XAccessibleContext > hitChild;
972cdf0e10cSrcweir    Reference < XAccessibleContext > emptyReference;
973cdf0e10cSrcweir    try {
974cdf0e10cSrcweir        Reference < XAccessibleComponent > rxAccessibleComponent ( rxAccessibleContext, UNO_QUERY );
975cdf0e10cSrcweir        if ( rxAccessibleComponent.is() ) {
976cdf0e10cSrcweir            com::sun::star::awt::Point location = rxAccessibleComponent -> getLocationOnScreen();
977cdf0e10cSrcweir            com::sun::star::awt::Point hitPoint ( point.X - location.X , point.Y - location.Y);
978cdf0e10cSrcweir            Reference < XAccessible > rxAccessible = rxAccessibleComponent -> getAccessibleAtPoint ( hitPoint );
979cdf0e10cSrcweir            if ( rxAccessible.is() && rxAccessible -> getAccessibleContext().is() ) {
980cdf0e10cSrcweir                if ( rxAccessible -> getAccessibleContext() -> getAccessibleChildCount() > 0 ) {
981cdf0e10cSrcweir                    hitChild = hitTestRunner ( point, rxAccessible -> getAccessibleContext() );
982cdf0e10cSrcweir                    if ( ! hitChild.is() ) {
983cdf0e10cSrcweir                        hitChild = rxAccessible -> getAccessibleContext();
984cdf0e10cSrcweir                    }
985cdf0e10cSrcweir                } else {
986cdf0e10cSrcweir                    hitChild = rxAccessible -> getAccessibleContext();
987cdf0e10cSrcweir                }
988cdf0e10cSrcweir            }
989cdf0e10cSrcweir        }
990cdf0e10cSrcweir        if ( !hitChild.is() && rxAccessibleContext -> getAccessibleChildCount() > 0 ) { // special treatment for e.g. comboboxes
991cdf0e10cSrcweir            for ( int i = 0; i < rxAccessibleContext -> getAccessibleChildCount(); i++ ) {
992cdf0e10cSrcweir                Reference < XAccessible > rxAccessibleChild = rxAccessibleContext -> getAccessibleChild ( i );
993cdf0e10cSrcweir                if ( rxAccessibleChild.is() && rxAccessibleChild -> getAccessibleContext().is() && rxAccessibleChild -> getAccessibleContext() -> getAccessibleRole() != AccessibleRole::LIST ) {
994cdf0e10cSrcweir                    Reference < XAccessibleContext > myHitChild = hitTestRunner ( point, rxAccessibleChild -> getAccessibleContext() );
995cdf0e10cSrcweir                    if ( myHitChild.is() ) {
996cdf0e10cSrcweir                        hitChild = myHitChild;
997cdf0e10cSrcweir                        break;
998cdf0e10cSrcweir                    }
999cdf0e10cSrcweir                }
1000cdf0e10cSrcweir            }
1001cdf0e10cSrcweir        }
1002cdf0e10cSrcweir    } catch ( RuntimeException ) {
1003cdf0e10cSrcweir        return emptyReference;
1004cdf0e10cSrcweir    }
1005cdf0e10cSrcweir    return hitChild;
1006cdf0e10cSrcweir}
1007cdf0e10cSrcweir
1008cdf0e10cSrcweir-(id)accessibilityHitTest:(NSPoint)point {
1009cdf0e10cSrcweir    static id wrapper = nil;
1010cdf0e10cSrcweir    if ( nil != wrapper ) {
1011cdf0e10cSrcweir        [ wrapper release ];
1012cdf0e10cSrcweir        wrapper = nil;
1013cdf0e10cSrcweir    }
1014cdf0e10cSrcweir    Reference < XAccessibleContext > hitChild;
1015cdf0e10cSrcweir    NSRect screenRect = [ [ NSScreen mainScreen ] frame ];
1016cdf0e10cSrcweir    com::sun::star::awt::Point hitPoint ( static_cast<long>(point.x) , static_cast<long>(screenRect.size.height - point.y) );
1017cdf0e10cSrcweir    // check child windows first
1018cdf0e10cSrcweir    NSWindow * window = (NSWindow *) [ self accessibilityAttributeValue: NSAccessibilityWindowAttribute ];
1019cdf0e10cSrcweir    NSArray * childWindows = [ window childWindows ];
1020cdf0e10cSrcweir    if ( [ childWindows count ] > 0 ) {
1021cdf0e10cSrcweir        NSWindow * element = nil;
1022cdf0e10cSrcweir        NSEnumerator * enumerator = [ childWindows objectEnumerator ];
1023cdf0e10cSrcweir        while ( ( element = [ enumerator nextObject ] ) && hitChild == nil ) {
1024cdf0e10cSrcweir            if ( [ element isKindOfClass: [ SalFrameWindow class ] ] && [ self isViewElement: element hitByPoint: point ] ) {
1025cdf0e10cSrcweir                // we have a child window that is hit
1026cdf0e10cSrcweir                Reference < XAccessibleRelationSet > relationSet = [ ( ( SalFrameWindow * ) element ) accessibleContext ] -> getAccessibleRelationSet();
1027cdf0e10cSrcweir                if ( relationSet.is() && relationSet -> containsRelation ( AccessibleRelationType::SUB_WINDOW_OF )) {
1028cdf0e10cSrcweir                    // we have a valid relation to the parent element
1029cdf0e10cSrcweir                    AccessibleRelation relation = relationSet -> getRelationByType ( AccessibleRelationType::SUB_WINDOW_OF );
1030cdf0e10cSrcweir                    for ( int i = 0; i < relation.TargetSet.getLength() && !hitChild.is(); i++ ) {
1031cdf0e10cSrcweir                        Reference < XAccessible > rxAccessible ( relation.TargetSet [ i ], UNO_QUERY );
1032cdf0e10cSrcweir                        if ( rxAccessible.is() && rxAccessible -> getAccessibleContext().is() ) {
1033cdf0e10cSrcweir                            // hit test for children of parent
1034cdf0e10cSrcweir                            hitChild = hitTestRunner ( hitPoint, rxAccessible -> getAccessibleContext() );
1035cdf0e10cSrcweir                        }
1036cdf0e10cSrcweir                    }
1037cdf0e10cSrcweir                }
1038cdf0e10cSrcweir            }
1039cdf0e10cSrcweir        }
1040cdf0e10cSrcweir    }
1041cdf0e10cSrcweir    // nothing hit yet, so check ourself
1042cdf0e10cSrcweir    if ( ! hitChild.is() ) {
1043cdf0e10cSrcweir        if ( mpReferenceWrapper == nil ) {
1044cdf0e10cSrcweir            [ self setDefaults: [ self accessibleContext ] ];
1045cdf0e10cSrcweir        }
1046cdf0e10cSrcweir        hitChild = hitTestRunner ( hitPoint, mpReferenceWrapper -> rAccessibleContext );
1047cdf0e10cSrcweir    }
1048cdf0e10cSrcweir    if ( hitChild.is() ) {
1049cdf0e10cSrcweir        wrapper = [ AquaA11yFactory wrapperForAccessibleContext: hitChild ];
1050cdf0e10cSrcweir    }
1051cdf0e10cSrcweir    if ( wrapper != nil ) {
1052cdf0e10cSrcweir        [ wrapper retain ]; // TODO: retain only when transient ?
1053cdf0e10cSrcweir    }
1054cdf0e10cSrcweir    return wrapper;
1055cdf0e10cSrcweir}
1056cdf0e10cSrcweir
1057cdf0e10cSrcweir#pragma mark -
1058cdf0e10cSrcweir#pragma mark Access Methods
1059cdf0e10cSrcweir
1060cdf0e10cSrcweir-(XAccessibleAction *)accessibleAction {
1061cdf0e10cSrcweir    return mpReferenceWrapper -> rAccessibleAction.get();
1062cdf0e10cSrcweir}
1063cdf0e10cSrcweir
1064cdf0e10cSrcweir-(XAccessibleContext *)accessibleContext {
1065cdf0e10cSrcweir    return mpReferenceWrapper -> rAccessibleContext.get();
1066cdf0e10cSrcweir}
1067cdf0e10cSrcweir
1068cdf0e10cSrcweir-(XAccessibleComponent *)accessibleComponent {
1069cdf0e10cSrcweir    return mpReferenceWrapper -> rAccessibleComponent.get();
1070cdf0e10cSrcweir}
1071cdf0e10cSrcweir
1072cdf0e10cSrcweir-(XAccessibleExtendedComponent *)accessibleExtendedComponent {
1073cdf0e10cSrcweir    return mpReferenceWrapper -> rAccessibleExtendedComponent.get();
1074cdf0e10cSrcweir}
1075cdf0e10cSrcweir
1076cdf0e10cSrcweir-(XAccessibleSelection *)accessibleSelection {
1077cdf0e10cSrcweir    return mpReferenceWrapper -> rAccessibleSelection.get();
1078cdf0e10cSrcweir}
1079cdf0e10cSrcweir
1080cdf0e10cSrcweir-(XAccessibleTable *)accessibleTable {
1081cdf0e10cSrcweir    return mpReferenceWrapper -> rAccessibleTable.get();
1082cdf0e10cSrcweir}
1083cdf0e10cSrcweir
1084cdf0e10cSrcweir-(XAccessibleText *)accessibleText {
1085cdf0e10cSrcweir    return mpReferenceWrapper -> rAccessibleText.get();
1086cdf0e10cSrcweir}
1087cdf0e10cSrcweir
1088cdf0e10cSrcweir-(XAccessibleEditableText *)accessibleEditableText {
1089cdf0e10cSrcweir    return mpReferenceWrapper -> rAccessibleEditableText.get();
1090cdf0e10cSrcweir}
1091cdf0e10cSrcweir
1092cdf0e10cSrcweir-(XAccessibleValue *)accessibleValue {
1093cdf0e10cSrcweir    return mpReferenceWrapper -> rAccessibleValue.get();
1094cdf0e10cSrcweir}
1095cdf0e10cSrcweir
1096cdf0e10cSrcweir-(XAccessibleTextAttributes *)accessibleTextAttributes {
1097cdf0e10cSrcweir    return mpReferenceWrapper -> rAccessibleTextAttributes.get();
1098cdf0e10cSrcweir}
1099cdf0e10cSrcweir
1100cdf0e10cSrcweir-(XAccessibleMultiLineText *)accessibleMultiLineText {
1101cdf0e10cSrcweir    return mpReferenceWrapper -> rAccessibleMultiLineText.get();
1102cdf0e10cSrcweir}
1103cdf0e10cSrcweir
110497dacec1SHerbert Dürr-(NSWindow*)windowForParent {
110597dacec1SHerbert Dürr    return [self window];
1106cdf0e10cSrcweir}
1107cdf0e10cSrcweir
1108cdf0e10cSrcweir// These four are for AXTextAreas only. They are needed, because bold and italic
1109cdf0e10cSrcweir// attributes have to be bound to a font on the Mac. Our UNO-API instead handles
1110cdf0e10cSrcweir// and reports them independently. When they occur we bundle them to a font with
1111cdf0e10cSrcweir// this information here to create a according NSFont.
1112cdf0e10cSrcweir-(void)setDefaultFontname:(NSString *)fontname {
1113cdf0e10cSrcweir    if ( mpDefaultFontname != nil ) {
1114cdf0e10cSrcweir        [ mpDefaultFontname release ];
1115cdf0e10cSrcweir    }
1116cdf0e10cSrcweir    mpDefaultFontname = fontname;
1117cdf0e10cSrcweir}
1118cdf0e10cSrcweir
1119cdf0e10cSrcweir-(NSString *)defaultFontname {
1120cdf0e10cSrcweir    return mpDefaultFontname;
1121cdf0e10cSrcweir}
1122cdf0e10cSrcweir
1123cdf0e10cSrcweir-(void)setDefaultFontsize:(float)fontsize {
1124cdf0e10cSrcweir    mDefaultFontsize = fontsize;
1125cdf0e10cSrcweir}
1126cdf0e10cSrcweir
1127cdf0e10cSrcweir-(float)defaultFontsize {
1128cdf0e10cSrcweir    return mDefaultFontsize;
1129cdf0e10cSrcweir}
1130cdf0e10cSrcweir
1131cdf0e10cSrcweir-(void)setActsAsRadioGroup:(BOOL)actsAsRadioGroup {
1132cdf0e10cSrcweir    mActsAsRadioGroup = actsAsRadioGroup;
1133cdf0e10cSrcweir}
1134cdf0e10cSrcweir
1135cdf0e10cSrcweir-(BOOL)actsAsRadioGroup {
1136cdf0e10cSrcweir    return mActsAsRadioGroup;
1137cdf0e10cSrcweir}
1138cdf0e10cSrcweir
1139cdf0e10cSrcweir+(void)setPopupMenuOpen:(BOOL)popupMenuOpen {
1140cdf0e10cSrcweir    isPopupMenuOpen = popupMenuOpen;
1141cdf0e10cSrcweir}
1142cdf0e10cSrcweir
1143cdf0e10cSrcweir@end
1144