xref: /trunk/main/toolkit/source/awt/vclxaccessiblecomponent.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_toolkit.hxx"
30 
31 
32 #include <com/sun/star/accessibility/AccessibleRole.hpp>
33 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
34 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
35 #include <com/sun/star/accessibility/XAccessibleEventListener.hpp>
36 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
37 #include <toolkit/awt/vclxaccessiblecomponent.hxx>
38 #include <toolkit/helper/externallock.hxx>
39 #include <toolkit/awt/vclxwindow.hxx>
40 #include <toolkit/helper/convert.hxx>
41 #include <toolkit/awt/vclxfont.hxx>
42 #include <vcl/dialog.hxx>
43 #include <vcl/window.hxx>
44 #include <tools/debug.hxx>
45 #include <unotools/accessiblestatesethelper.hxx>
46 #include <unotools/accessiblerelationsethelper.hxx>
47 #include <vcl/svapp.hxx>
48 #include <vcl/menu.hxx>
49 
50 #ifndef VCLEVENT_WINDOW_FRAMETITLECHANGED
51 #define VCLEVENT_WINDOW_FRAMETITLECHANGED   1018    // pData = XubString* = oldTitle
52 #endif
53 
54 using namespace ::com::sun::star;
55 using namespace ::comphelper;
56 
57 
58 DBG_NAME(VCLXAccessibleComponent)
59 
60 
61 //  ----------------------------------------------------
62 //  class VCLXAccessibleComponent
63 //  ----------------------------------------------------
64 VCLXAccessibleComponent::VCLXAccessibleComponent( VCLXWindow* pVCLXindow )
65     : AccessibleExtendedComponentHelper_BASE( new VCLExternalSolarLock() )
66     , OAccessibleImplementationAccess( )
67 {
68     DBG_CTOR( VCLXAccessibleComponent, 0 );
69     mpVCLXindow = pVCLXindow;
70     mxWindow = pVCLXindow;
71 
72     m_pSolarLock = static_cast< VCLExternalSolarLock* >( getExternalLock( ) );
73 
74     DBG_ASSERT( pVCLXindow->GetWindow(), "VCLXAccessibleComponent - no window!" );
75     if ( pVCLXindow->GetWindow() )
76     {
77       pVCLXindow->GetWindow()->AddEventListener( LINK( this, VCLXAccessibleComponent, WindowEventListener ) );
78       pVCLXindow->GetWindow()->AddChildEventListener( LINK( this, VCLXAccessibleComponent, WindowChildEventListener ) );
79     }
80 
81     // announce the XAccessible of our creator to the base class
82     lateInit( pVCLXindow );
83 }
84 
85 VCLXAccessibleComponent::~VCLXAccessibleComponent()
86 {
87     DBG_DTOR( VCLXAccessibleComponent, 0 );
88 
89     ensureDisposed();
90 
91     if ( mpVCLXindow && mpVCLXindow->GetWindow() )
92     {
93         mpVCLXindow->GetWindow()->RemoveEventListener( LINK( this, VCLXAccessibleComponent, WindowEventListener ) );
94         mpVCLXindow->GetWindow()->RemoveChildEventListener( LINK( this, VCLXAccessibleComponent, WindowChildEventListener ) );
95     }
96 
97     delete m_pSolarLock;
98     m_pSolarLock = NULL;
99     // This is not completely safe. If we assume that the base class dtor calls some method which
100     // uses this lock, the we crash. However, as the base class' dtor does not have a chance to call _out_
101     // virtual methods, this is no problem as long as the base class is safe, i.e. does not use the external
102     // lock from within it's dtor. At the moment, we _know_ the base class is safe in this respect, so
103     // let's assume it keeps this way.
104     // @see OAccessibleContextHelper::OAccessibleContextHelper( IMutex* )
105 }
106 
107 IMPLEMENT_FORWARD_XINTERFACE3( VCLXAccessibleComponent, AccessibleExtendedComponentHelper_BASE, OAccessibleImplementationAccess, VCLXAccessibleComponent_BASE )
108 IMPLEMENT_FORWARD_XTYPEPROVIDER3( VCLXAccessibleComponent, AccessibleExtendedComponentHelper_BASE, OAccessibleImplementationAccess, VCLXAccessibleComponent_BASE )
109 
110 ::rtl::OUString VCLXAccessibleComponent::getImplementationName() throw (uno::RuntimeException)
111 {
112     return ::rtl::OUString::createFromAscii( "com.sun.star.comp.toolkit.AccessibleWindow" );
113 }
114 
115 sal_Bool VCLXAccessibleComponent::supportsService( const ::rtl::OUString& rServiceName ) throw (uno::RuntimeException)
116 {
117     uno::Sequence< ::rtl::OUString > aNames( getSupportedServiceNames() );
118     const ::rtl::OUString* pNames = aNames.getConstArray();
119     const ::rtl::OUString* pEnd = pNames + aNames.getLength();
120     for ( ; pNames != pEnd && !pNames->equals( rServiceName ); ++pNames )
121         ;
122 
123     return pNames != pEnd;
124 }
125 
126 uno::Sequence< ::rtl::OUString > VCLXAccessibleComponent::getSupportedServiceNames() throw (uno::RuntimeException)
127 {
128     uno::Sequence< ::rtl::OUString > aNames(1);
129     aNames[0] = ::rtl::OUString::createFromAscii( "com.sun.star.awt.AccessibleWindow" );
130     return aNames;
131 }
132 
133 IMPL_LINK( VCLXAccessibleComponent, WindowEventListener, VclSimpleEvent*, pEvent )
134 {
135     DBG_CHKTHIS(VCLXAccessibleComponent,0);
136 
137     DBG_ASSERT( pEvent && pEvent->ISA( VclWindowEvent ), "Unknown WindowEvent!" );
138 
139         /* Ignore VCLEVENT_WINDOW_ENDPOPUPMODE, because the UNO accessibility wrapper
140          * might have been destroyed by the previous VCLEventListener (if no AT tool
141          * is running), e.g. sub-toolbars in impress.
142          */
143     if ( pEvent && pEvent->ISA( VclWindowEvent ) && mxWindow.is() /* #122218# */ && (pEvent->GetId() != VCLEVENT_WINDOW_ENDPOPUPMODE) )
144     {
145         DBG_ASSERT( ((VclWindowEvent*)pEvent)->GetWindow(), "Window???" );
146         if( !((VclWindowEvent*)pEvent)->GetWindow()->IsAccessibilityEventsSuppressed() || ( pEvent->GetId() == VCLEVENT_OBJECT_DYING ) )
147         {
148             ProcessWindowEvent( *(VclWindowEvent*)pEvent );
149         }
150     }
151     return 0;
152 }
153 
154 IMPL_LINK( VCLXAccessibleComponent, WindowChildEventListener, VclSimpleEvent*, pEvent )
155 {
156     DBG_CHKTHIS(VCLXAccessibleComponent,0);
157 
158     DBG_ASSERT( pEvent && pEvent->ISA( VclWindowEvent ), "Unknown WindowEvent!" );
159     if ( pEvent && pEvent->ISA( VclWindowEvent ) && mxWindow.is() /* #i68079# */ )
160     {
161         DBG_ASSERT( ((VclWindowEvent*)pEvent)->GetWindow(), "Window???" );
162         if( !((VclWindowEvent*)pEvent)->GetWindow()->IsAccessibilityEventsSuppressed() )
163         {
164             // #103087# to prevent an early release of the component
165             uno::Reference< accessibility::XAccessibleContext > xTmp = this;
166 
167             ProcessWindowChildEvent( *(VclWindowEvent*)pEvent );
168         }
169     }
170     return 0;
171 }
172 
173 uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::GetChildAccessible( const VclWindowEvent& rVclWindowEvent )
174 {
175     // checks if the data in the window event is our direct child
176     // and returns its accessible
177 
178     // MT: Change this later, normaly a show/hide event shouldn't have the Window* in pData.
179     Window* pChildWindow = (Window *) rVclWindowEvent.GetData();
180     if( pChildWindow && GetWindow() == pChildWindow->GetAccessibleParentWindow() )
181         return pChildWindow->GetAccessible( rVclWindowEvent.GetId() == VCLEVENT_WINDOW_SHOW );
182     else
183         return uno::Reference< accessibility::XAccessible > ();
184 }
185 
186 void VCLXAccessibleComponent::ProcessWindowChildEvent( const VclWindowEvent& rVclWindowEvent )
187 {
188     uno::Any aOldValue, aNewValue;
189     uno::Reference< accessibility::XAccessible > xAcc;
190 
191     switch ( rVclWindowEvent.GetId() )
192     {
193         case VCLEVENT_WINDOW_SHOW:  // send create on show for direct accessible children
194         {
195             xAcc = GetChildAccessible( rVclWindowEvent );
196             if( xAcc.is() )
197             {
198                 aNewValue <<= xAcc;
199                 NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
200             }
201         }
202         break;
203         case VCLEVENT_WINDOW_HIDE:  // send destroy on hide for direct accessible children
204         {
205             xAcc = GetChildAccessible( rVclWindowEvent );
206             if( xAcc.is() )
207             {
208                 aOldValue <<= xAcc;
209                 NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
210             }
211         }
212         break;
213     }
214 }
215 
216 void VCLXAccessibleComponent::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
217 {
218     uno::Any aOldValue, aNewValue;
219 
220     Window* pAccWindow = rVclWindowEvent.GetWindow();
221     DBG_ASSERT( pAccWindow, "VCLXAccessibleComponent::ProcessWindowEvent - Window?" );
222 
223     switch ( rVclWindowEvent.GetId() )
224     {
225         case VCLEVENT_OBJECT_DYING:
226         {
227             pAccWindow->RemoveEventListener( LINK( this, VCLXAccessibleComponent, WindowEventListener ) );
228             pAccWindow->RemoveChildEventListener( LINK( this, VCLXAccessibleComponent, WindowChildEventListener ) );
229             mxWindow.clear();
230             mpVCLXindow = NULL;
231         }
232         break;
233         //
234         // dont handle CHILDCREATED events here
235         // they are handled separately as child events, see ProcessWindowChildEvent above
236         //
237         /*
238         case VCLEVENT_WINDOW_CHILDCREATED:
239         {
240             Window* pWindow = (Window*) rVclWindowEvent.GetData();
241             DBG_ASSERT( pWindow, "VCLEVENT_WINDOW_CHILDCREATED - Window=?" );
242             aNewValue <<= pWindow->GetAccessible();
243             NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
244         }
245         break;
246         */
247         case VCLEVENT_WINDOW_CHILDDESTROYED:
248         {
249             Window* pWindow = (Window*) rVclWindowEvent.GetData();
250             DBG_ASSERT( pWindow, "VCLEVENT_WINDOW_CHILDDESTROYED - Window=?" );
251             if ( pWindow->GetAccessible( sal_False ).is() )
252             {
253                 aOldValue <<= pWindow->GetAccessible( sal_False );
254                 NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
255             }
256         }
257         break;
258 
259         //
260         // show and hide will be handled as child events only and are
261         // responsible for sending create/destroy events, see ProcessWindowChildEvent above
262         //
263         /*
264         case VCLEVENT_WINDOW_SHOW:
265         {
266             aNewValue <<= accessibility::AccessibleStateType::VISIBLE;
267             NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
268 
269             aNewValue <<= accessibility::AccessibleStateType::SHOWING;
270             NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
271 
272             aNewValue.clear();
273             aOldValue <<= accessibility::AccessibleStateType::INVALID;
274             NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
275         }
276         break;
277         case VCLEVENT_WINDOW_HIDE:
278         {
279             aOldValue <<= accessibility::AccessibleStateType::VISIBLE;
280             NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
281 
282             aOldValue <<= accessibility::AccessibleStateType::SHOWING;
283             NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
284 
285             aOldValue.clear();
286             aNewValue <<= accessibility::AccessibleStateType::INVALID;
287             NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
288         }
289         break;
290         */
291         case VCLEVENT_WINDOW_ACTIVATE:
292         {
293             // avoid notification if a child frame is already active
294             // only one frame may be active at a given time
295             if ( !pAccWindow->HasActiveChildFrame() &&
296                  ( getAccessibleRole() == accessibility::AccessibleRole::FRAME ||
297                    getAccessibleRole() == accessibility::AccessibleRole::ALERT ||
298                    getAccessibleRole() == accessibility::AccessibleRole::DIALOG ) )  // #i18891#
299             {
300                 aNewValue <<= accessibility::AccessibleStateType::ACTIVE;
301                 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
302             }
303         }
304         break;
305         case VCLEVENT_WINDOW_DEACTIVATE:
306         {
307             if ( getAccessibleRole() == accessibility::AccessibleRole::FRAME ||
308                  getAccessibleRole() == accessibility::AccessibleRole::ALERT ||
309                  getAccessibleRole() == accessibility::AccessibleRole::DIALOG )  // #i18891#
310             {
311                 aOldValue <<= accessibility::AccessibleStateType::ACTIVE;
312                 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
313             }
314         }
315         break;
316         case VCLEVENT_WINDOW_GETFOCUS:
317         case VCLEVENT_CONTROL_GETFOCUS:
318         {
319             if( (pAccWindow->IsCompoundControl() && rVclWindowEvent.GetId() == VCLEVENT_CONTROL_GETFOCUS) ||
320                 (!pAccWindow->IsCompoundControl() && rVclWindowEvent.GetId() == VCLEVENT_WINDOW_GETFOCUS) )
321             {
322                 // if multiple listeners were registered it is possible that the
323                 // focus was changed during event processing (eg SfxTopWindow )
324                 // #106082# allow ChildPathFocus only for CompoundControls, for windows the focus must be in the window itself
325                 if( (pAccWindow->IsCompoundControl() && pAccWindow->HasChildPathFocus()) ||
326                     (!pAccWindow->IsCompoundControl() && pAccWindow->HasFocus()) )
327                 {
328                     aNewValue <<= accessibility::AccessibleStateType::FOCUSED;
329                     NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
330                 }
331             }
332         }
333         break;
334         case VCLEVENT_WINDOW_LOSEFOCUS:
335         case VCLEVENT_CONTROL_LOSEFOCUS:
336         {
337             if( (pAccWindow->IsCompoundControl() && rVclWindowEvent.GetId() == VCLEVENT_CONTROL_LOSEFOCUS) ||
338                 (!pAccWindow->IsCompoundControl() && rVclWindowEvent.GetId() == VCLEVENT_WINDOW_LOSEFOCUS) )
339             {
340                 aOldValue <<= accessibility::AccessibleStateType::FOCUSED;
341                 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
342             }
343         }
344         break;
345         case VCLEVENT_WINDOW_FRAMETITLECHANGED:
346         {
347             ::rtl::OUString aOldName( *((::rtl::OUString*) rVclWindowEvent.GetData()) );
348             ::rtl::OUString aNewName( getAccessibleName() );
349             aOldValue <<= aOldName;
350             aNewValue <<= aNewName;
351             NotifyAccessibleEvent( accessibility::AccessibleEventId::NAME_CHANGED, aOldValue, aNewValue );
352         }
353         break;
354         case VCLEVENT_WINDOW_ENABLED:
355         {
356             aNewValue <<= accessibility::AccessibleStateType::ENABLED;
357             NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
358             aNewValue <<= accessibility::AccessibleStateType::SENSITIVE;
359             NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
360         }
361         break;
362         case VCLEVENT_WINDOW_DISABLED:
363         {
364             aOldValue <<= accessibility::AccessibleStateType::SENSITIVE;
365             NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
366 
367             aOldValue <<= accessibility::AccessibleStateType::ENABLED;
368             NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
369         }
370         break;
371         case VCLEVENT_WINDOW_MOVE:
372         case VCLEVENT_WINDOW_RESIZE:
373         {
374             NotifyAccessibleEvent( accessibility::AccessibleEventId::BOUNDRECT_CHANGED, aOldValue, aNewValue );
375         }
376         break;
377         case VCLEVENT_WINDOW_MENUBARADDED:
378         {
379             MenuBar* pMenuBar = (MenuBar*) rVclWindowEvent.GetData();
380             if ( pMenuBar )
381             {
382                 uno::Reference< accessibility::XAccessible > xChild( pMenuBar->GetAccessible() );
383                 if ( xChild.is() )
384                 {
385                     aNewValue <<= xChild;
386                     NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
387                 }
388             }
389         }
390         break;
391         case VCLEVENT_WINDOW_MENUBARREMOVED:
392         {
393             MenuBar* pMenuBar = (MenuBar*) rVclWindowEvent.GetData();
394             if ( pMenuBar )
395             {
396                 uno::Reference< accessibility::XAccessible > xChild( pMenuBar->GetAccessible() );
397                 if ( xChild.is() )
398                 {
399                     aOldValue <<= xChild;
400                     NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
401                 }
402             }
403         }
404         break;
405         case VCLEVENT_WINDOW_MINIMIZE:
406         {
407             aNewValue <<= accessibility::AccessibleStateType::ICONIFIED;
408             NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
409         }
410         break;
411         case VCLEVENT_WINDOW_NORMALIZE:
412         {
413             aOldValue <<= accessibility::AccessibleStateType::ICONIFIED;
414             NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
415         }
416         break;
417         default:
418         {
419         }
420         break;
421     }
422 }
423 
424 void VCLXAccessibleComponent::disposing()
425 {
426     if ( mpVCLXindow && mpVCLXindow->GetWindow() )
427     {
428         mpVCLXindow->GetWindow()->RemoveEventListener( LINK( this, VCLXAccessibleComponent, WindowEventListener ) );
429         mpVCLXindow->GetWindow()->RemoveChildEventListener( LINK( this, VCLXAccessibleComponent, WindowChildEventListener ) );
430     }
431 
432     AccessibleExtendedComponentHelper_BASE::disposing();
433 
434     mxWindow.clear();
435     mpVCLXindow = NULL;
436 }
437 
438 Window* VCLXAccessibleComponent::GetWindow() const
439 {
440     return GetVCLXWindow() ? GetVCLXWindow()->GetWindow() : NULL;
441 }
442 
443 void VCLXAccessibleComponent::FillAccessibleRelationSet( utl::AccessibleRelationSetHelper& rRelationSet )
444 {
445     Window* pWindow = GetWindow();
446     if ( pWindow )
447     {
448         Window *pLabeledBy = pWindow->GetAccessibleRelationLabeledBy();
449         if ( pLabeledBy && pLabeledBy != pWindow )
450         {
451             uno::Sequence< uno::Reference< uno::XInterface > > aSequence(1);
452             aSequence[0] = pLabeledBy->GetAccessible();
453             rRelationSet.AddRelation( accessibility::AccessibleRelation( accessibility::AccessibleRelationType::LABELED_BY, aSequence ) );
454         }
455 
456         Window* pLabelFor = pWindow->GetAccessibleRelationLabelFor();
457         if ( pLabelFor && pLabelFor != pWindow )
458         {
459             uno::Sequence< uno::Reference< uno::XInterface > > aSequence(1);
460             aSequence[0] = pLabelFor->GetAccessible();
461             rRelationSet.AddRelation( accessibility::AccessibleRelation( accessibility::AccessibleRelationType::LABEL_FOR, aSequence ) );
462         }
463     }
464 }
465 
466 void VCLXAccessibleComponent::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
467 {
468     Window* pWindow = GetWindow();
469     if ( pWindow )
470     {
471         if ( pWindow->IsVisible() )
472         {
473             rStateSet.AddState( accessibility::AccessibleStateType::VISIBLE );
474             rStateSet.AddState( accessibility::AccessibleStateType::SHOWING );
475         }
476         else
477         {
478             rStateSet.AddState( accessibility::AccessibleStateType::INVALID );
479         }
480 
481         if ( pWindow->IsEnabled() )
482         {
483             rStateSet.AddState( accessibility::AccessibleStateType::ENABLED );
484             rStateSet.AddState( accessibility::AccessibleStateType::SENSITIVE );
485         }
486 
487         if ( pWindow->HasChildPathFocus() &&
488              ( getAccessibleRole() == accessibility::AccessibleRole::FRAME ||
489                getAccessibleRole() == accessibility::AccessibleRole::ALERT ||
490                getAccessibleRole() == accessibility::AccessibleRole::DIALOG ) )  // #i18891#
491             rStateSet.AddState( accessibility::AccessibleStateType::ACTIVE );
492 
493         // #104290# MT: This way, a ComboBox doesn't get state FOCUSED.
494         // I also don't understand
495         // a) why WINDOW_FIRSTCHILD is used here (which btw is a border window in the case of a combo box)
496         // b) why HasFocus() is nout "enough" for a compound control
497         /*
498         Window* pChild = pWindow->GetWindow( WINDOW_FIRSTCHILD );
499         if ( ( !pWindow->IsCompoundControl() && pWindow->HasFocus() ) ||
500              ( pWindow->IsCompoundControl() && pChild && pChild->HasFocus() ) )
501             rStateSet.AddState( accessibility::AccessibleStateType::FOCUSED );
502         */
503         if ( pWindow->HasFocus() || ( pWindow->IsCompoundControl() && pWindow->HasChildPathFocus() ) )
504             rStateSet.AddState( accessibility::AccessibleStateType::FOCUSED );
505 
506         if ( pWindow->IsWait() )
507             rStateSet.AddState( accessibility::AccessibleStateType::BUSY );
508 
509         if ( pWindow->GetStyle() & WB_SIZEABLE )
510             rStateSet.AddState( accessibility::AccessibleStateType::RESIZABLE );
511 
512         if( pWindow->IsDialog() )
513         {
514             Dialog *pDlg = static_cast< Dialog* >( pWindow );
515             if( pDlg->IsInExecute() )
516                 rStateSet.AddState( accessibility::AccessibleStateType::MODAL );
517         }
518     }
519     else
520     {
521         rStateSet.AddState( accessibility::AccessibleStateType::DEFUNC );
522     }
523 
524 /*
525 
526 MUST BE SET FROM DERIVED CLASSES:
527 
528 CHECKED
529 COLLAPSED
530 EXPANDED
531 EXPANDABLE
532 EDITABLE
533 FOCUSABLE
534 HORIZONTAL
535 VERTICAL
536 ICONIFIED
537 MULTILINE
538 MULTI_SELECTABLE
539 PRESSED
540 SELECTABLE
541 SELECTED
542 SINGLE_LINE
543 TRANSIENT
544 
545     */
546 }
547 
548 
549 // accessibility::XAccessibleContext
550 sal_Int32 VCLXAccessibleComponent::getAccessibleChildCount() throw (uno::RuntimeException)
551 {
552     OExternalLockGuard aGuard( this );
553 
554     sal_Int32 nChildren = 0;
555     if ( GetWindow() )
556         nChildren = GetWindow()->GetAccessibleChildWindowCount();
557 
558     return nChildren;
559 }
560 
561 uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::getAccessibleChild( sal_Int32 i ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
562 {
563     OExternalLockGuard aGuard( this );
564 
565     if ( i >= getAccessibleChildCount() )
566         throw lang::IndexOutOfBoundsException();
567 
568     uno::Reference< accessibility::XAccessible > xAcc;
569     if ( GetWindow() )
570     {
571         Window* pChild = GetWindow()->GetAccessibleChildWindow( (sal_uInt16)i );
572         if ( pChild )
573             xAcc = pChild->GetAccessible();
574     }
575 
576     return xAcc;
577 }
578 
579 uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::getVclParent() const
580 {
581     uno::Reference< accessibility::XAccessible > xAcc;
582     if ( GetWindow() )
583     {
584         Window* pParent = GetWindow()->GetAccessibleParentWindow();
585         if ( pParent )
586             xAcc = pParent->GetAccessible();
587     }
588     return xAcc;
589 }
590 
591 uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::getAccessibleParent(  ) throw (uno::RuntimeException)
592 {
593     OExternalLockGuard aGuard( this );
594 
595     uno::Reference< accessibility::XAccessible > xAcc( implGetForeignControlledParent() );
596     if ( !xAcc.is() )
597         // we do _not_ have a foreign-controlled parent -> default to our VCL parent
598         xAcc = getVclParent();
599 
600     return xAcc;
601 }
602 
603 sal_Int32 VCLXAccessibleComponent::getAccessibleIndexInParent(  ) throw (uno::RuntimeException)
604 {
605     OExternalLockGuard aGuard( this );
606 
607     sal_Int32 nIndex = -1;
608 
609     uno::Reference< accessibility::XAccessible > xAcc( implGetForeignControlledParent() );
610     if ( xAcc.is() )
611     {   // we _do_ have a foreign-controlled parent -> use the base class' implementation,
612         // which goes the UNO way
613         nIndex = AccessibleExtendedComponentHelper_BASE::getAccessibleIndexInParent( );
614     }
615     else
616     {
617         if ( GetWindow() )
618         {
619             Window* pParent = GetWindow()->GetAccessibleParentWindow();
620             if ( pParent )
621             {
622                 /*
623                 for ( sal_uInt16 n = pParent->GetAccessibleChildWindowCount(); n; )
624                 {
625                     Window* pChild = pParent->GetAccessibleChildWindow( --n );
626                     if ( pChild == GetWindow() )
627                     {
628                         nIndex = n;
629                         break;
630                     }
631                 }
632                 */
633                 //  Iterate over all the parent's children and search for this object.
634                 // this should be compatible with the code in SVX
635                 uno::Reference< accessibility::XAccessible > xParentAcc( pParent->GetAccessible() );
636                 if ( xParentAcc.is() )
637                 {
638                     uno::Reference< accessibility::XAccessibleContext > xParentContext ( xParentAcc->getAccessibleContext() );
639                     if ( xParentContext.is() )
640                     {
641                         sal_Int32 nChildCount = xParentContext->getAccessibleChildCount();
642                         for ( sal_Int32 i=0; i<nChildCount; i++ )
643                         {
644                             uno::Reference< accessibility::XAccessible > xChild( xParentContext->getAccessibleChild(i) );
645                             if ( xChild.is() )
646                             {
647                                 uno::Reference< accessibility::XAccessibleContext > xChildContext = xChild->getAccessibleContext();
648                                 if ( xChildContext == (accessibility::XAccessibleContext*) this )
649                                 {
650                                     nIndex = i;
651                                     break;
652                                 }
653                             }
654                         }
655                     }
656                 }
657             }
658         }
659     }
660     return nIndex;
661 }
662 
663 sal_Int16 VCLXAccessibleComponent::getAccessibleRole(  ) throw (uno::RuntimeException)
664 {
665     OExternalLockGuard aGuard( this );
666 
667     sal_Int16 nRole = 0;
668 
669     if ( GetWindow() )
670         nRole = GetWindow()->GetAccessibleRole();
671 
672     return nRole;
673 }
674 
675 ::rtl::OUString VCLXAccessibleComponent::getAccessibleDescription(  ) throw (uno::RuntimeException)
676 {
677     OExternalLockGuard aGuard( this );
678 
679     ::rtl::OUString aDescription;
680 
681     if ( GetWindow() )
682         aDescription = GetWindow()->GetAccessibleDescription();
683 
684     return aDescription;
685 }
686 
687 ::rtl::OUString VCLXAccessibleComponent::getAccessibleName(  ) throw (uno::RuntimeException)
688 {
689     OExternalLockGuard aGuard( this );
690 
691     ::rtl::OUString aName;
692     if ( GetWindow() )
693     {
694         aName = GetWindow()->GetAccessibleName();
695 #if OSL_DEBUG_LEVEL > 1
696         aName += String( RTL_CONSTASCII_USTRINGPARAM( " (Type = " ) );
697         aName += String::CreateFromInt32( GetWindow()->GetType() );
698         aName += String( RTL_CONSTASCII_USTRINGPARAM( ")" ) );
699 #endif
700     }
701     return aName;
702 }
703 
704 uno::Reference< accessibility::XAccessibleRelationSet > VCLXAccessibleComponent::getAccessibleRelationSet(  ) throw (uno::RuntimeException)
705 {
706     OExternalLockGuard aGuard( this );
707 
708     utl::AccessibleRelationSetHelper* pRelationSetHelper = new utl::AccessibleRelationSetHelper;
709     uno::Reference< accessibility::XAccessibleRelationSet > xSet = pRelationSetHelper;
710     FillAccessibleRelationSet( *pRelationSetHelper );
711     return xSet;
712 }
713 
714 uno::Reference< accessibility::XAccessibleStateSet > VCLXAccessibleComponent::getAccessibleStateSet(  ) throw (uno::RuntimeException)
715 {
716     OExternalLockGuard aGuard( this );
717 
718     utl::AccessibleStateSetHelper* pStateSetHelper = new utl::AccessibleStateSetHelper;
719     uno::Reference< accessibility::XAccessibleStateSet > xSet = pStateSetHelper;
720     FillAccessibleStateSet( *pStateSetHelper );
721     return xSet;
722 }
723 
724 lang::Locale VCLXAccessibleComponent::getLocale() throw (accessibility::IllegalAccessibleComponentStateException, uno::RuntimeException)
725 {
726     OExternalLockGuard aGuard( this );
727 
728     return Application::GetSettings().GetLocale();
729 }
730 
731 uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::getAccessibleAtPoint( const awt::Point& rPoint ) throw (uno::RuntimeException)
732 {
733     OExternalLockGuard aGuard( this );
734 
735     uno::Reference< accessibility::XAccessible > xChild;
736     for ( sal_uInt32 i = 0, nCount = getAccessibleChildCount(); i < nCount; ++i )
737     {
738         uno::Reference< accessibility::XAccessible > xAcc = getAccessibleChild( i );
739         if ( xAcc.is() )
740         {
741             uno::Reference< accessibility::XAccessibleComponent > xComp( xAcc->getAccessibleContext(), uno::UNO_QUERY );
742             if ( xComp.is() )
743             {
744                 Rectangle aRect = VCLRectangle( xComp->getBounds() );
745                 Point aPos = VCLPoint( rPoint );
746                 if ( aRect.IsInside( aPos ) )
747                 {
748                     xChild = xAcc;
749                     break;
750                 }
751             }
752         }
753     }
754 
755     return xChild;
756 }
757 
758 // accessibility::XAccessibleComponent
759 awt::Rectangle VCLXAccessibleComponent::implGetBounds() throw (uno::RuntimeException)
760 {
761     awt::Rectangle aBounds ( 0, 0, 0, 0 );
762 
763     Window* pWindow = GetWindow();
764     if ( pWindow )
765     {
766         Rectangle aRect = pWindow->GetWindowExtentsRelative( NULL );
767         aBounds = AWTRectangle( aRect );
768         Window* pParent = pWindow->GetAccessibleParentWindow();
769         if ( pParent )
770         {
771             Rectangle aParentRect = pParent->GetWindowExtentsRelative( NULL );
772             awt::Point aParentScreenLoc = AWTPoint( aParentRect.TopLeft() );
773             aBounds.X -= aParentScreenLoc.X;
774             aBounds.Y -= aParentScreenLoc.Y;
775         }
776     }
777 
778     uno::Reference< accessibility::XAccessible > xParent( implGetForeignControlledParent() );
779     if ( xParent.is() )
780     {   // hmm, we can't rely on our VCL coordinates, as in the Accessibility Hierarchy, somebody gave
781         // us a parent which is different from our VCL parent
782         // (actually, we did not check if it's really different ...)
783 
784         // the screen location of the foreign parent
785         uno::Reference< accessibility::XAccessibleComponent > xParentComponent( xParent->getAccessibleContext(), uno::UNO_QUERY );
786         DBG_ASSERT( xParentComponent.is(), "VCLXAccessibleComponent::implGetBounds: invalid (foreign) parent component!" );
787 
788         awt::Point aScreenLocForeign( 0, 0 );
789         if ( xParentComponent.is() )
790             aScreenLocForeign = xParentComponent->getLocationOnScreen();
791 
792         // the screen location of the VCL parent
793         xParent = getVclParent();
794         if ( xParent.is() )
795             xParentComponent = xParentComponent.query( xParent->getAccessibleContext() );
796 
797         awt::Point aScreenLocVCL( 0, 0 );
798         if ( xParentComponent.is() )
799             aScreenLocVCL = xParentComponent->getLocationOnScreen();
800 
801         // the difference between them
802         awt::Size aOffset( aScreenLocVCL.X - aScreenLocForeign.X, aScreenLocVCL.Y - aScreenLocForeign.Y );
803         // move the bounds
804         aBounds.X += aOffset.Width;
805         aBounds.Y += aOffset.Height;
806     }
807 
808     return aBounds;
809 }
810 
811 awt::Point VCLXAccessibleComponent::getLocationOnScreen(  ) throw (uno::RuntimeException)
812 {
813     OExternalLockGuard aGuard( this );
814 
815     awt::Point aPos;
816     if ( GetWindow() )
817     {
818         Rectangle aRect = GetWindow()->GetWindowExtentsRelative( NULL );
819         aPos.X = aRect.Left();
820         aPos.Y = aRect.Top();
821     }
822 
823     return aPos;
824 }
825 
826 void VCLXAccessibleComponent::grabFocus(  ) throw (uno::RuntimeException)
827 {
828     OExternalLockGuard aGuard( this );
829 
830     uno::Reference< accessibility::XAccessibleStateSet > xStates = getAccessibleStateSet();
831     if ( mxWindow.is() && xStates.is() && xStates->contains( accessibility::AccessibleStateType::FOCUSABLE ) )
832         mxWindow->setFocus();
833 }
834 
835 sal_Int32 SAL_CALL VCLXAccessibleComponent::getForeground(  ) throw (uno::RuntimeException)
836 {
837     OExternalLockGuard aGuard( this );
838 
839     sal_Int32 nColor = 0;
840     Window* pWindow = GetWindow();
841     if ( pWindow )
842     {
843         if ( pWindow->IsControlForeground() )
844             nColor = pWindow->GetControlForeground().GetColor();
845         else
846         {
847             Font aFont;
848             if ( pWindow->IsControlFont() )
849                 aFont = pWindow->GetControlFont();
850             else
851                 aFont = pWindow->GetFont();
852             nColor = aFont.GetColor().GetColor();
853         }
854     }
855 
856     return nColor;
857 }
858 
859 sal_Int32 SAL_CALL VCLXAccessibleComponent::getBackground(  ) throw (uno::RuntimeException)
860 {
861     OExternalLockGuard aGuard( this );
862 
863     sal_Int32 nColor = 0;
864     Window* pWindow = GetWindow();
865     if ( pWindow )
866     {
867         if ( pWindow->IsControlBackground() )
868             nColor = pWindow->GetControlBackground().GetColor();
869         else
870             nColor = pWindow->GetBackground().GetColor().GetColor();
871     }
872 
873     return nColor;
874 }
875 
876 // XAccessibleExtendedComponent
877 
878 uno::Reference< awt::XFont > SAL_CALL VCLXAccessibleComponent::getFont(  ) throw (uno::RuntimeException)
879 {
880     OExternalLockGuard aGuard( this );
881 
882     uno::Reference< awt::XFont > xFont;
883     Window* pWindow = GetWindow();
884     if ( pWindow )
885     {
886         uno::Reference< awt::XDevice > xDev( pWindow->GetComponentInterface(), uno::UNO_QUERY );
887         if ( xDev.is() )
888         {
889             Font aFont;
890             if ( pWindow->IsControlFont() )
891                 aFont = pWindow->GetControlFont();
892             else
893                 aFont = pWindow->GetFont();
894             VCLXFont* pVCLXFont = new VCLXFont;
895             pVCLXFont->Init( *xDev.get(), aFont );
896             xFont = pVCLXFont;
897         }
898     }
899 
900     return xFont;
901 }
902 
903 ::rtl::OUString SAL_CALL VCLXAccessibleComponent::getTitledBorderText(  ) throw (uno::RuntimeException)
904 {
905     OExternalLockGuard aGuard( this );
906 
907     ::rtl::OUString sRet;
908     if ( GetWindow() )
909         sRet = GetWindow()->GetText();
910 
911     return sRet;
912 }
913 
914 ::rtl::OUString SAL_CALL VCLXAccessibleComponent::getToolTipText(  ) throw (uno::RuntimeException)
915 {
916     OExternalLockGuard aGuard( this );
917 
918     ::rtl::OUString sRet;
919     if ( GetWindow() )
920         sRet = GetWindow()->GetQuickHelpText();
921 
922     return sRet;
923 }
924 
925