merge the formfield patch from ooo-build
[ooovba.git] / toolkit / source / awt / vclxaccessiblecomponent.cxx
blob34cfd932bad6ee97350f3592bcbc506de5c7360f
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: vclxaccessiblecomponent.cxx,v $
10 * $Revision: 1.59 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_toolkit.hxx"
35 #include <com/sun/star/accessibility/AccessibleRole.hpp>
36 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
37 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
38 #include <com/sun/star/accessibility/XAccessibleEventListener.hpp>
39 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
40 #include <toolkit/awt/vclxaccessiblecomponent.hxx>
41 #include <toolkit/helper/externallock.hxx>
42 #include <toolkit/awt/vclxwindow.hxx>
43 #include <toolkit/helper/convert.hxx>
44 #include <toolkit/awt/vclxfont.hxx>
45 #include <vcl/dialog.hxx>
46 #include <vcl/window.hxx>
47 #include <tools/debug.hxx>
48 #include <unotools/accessiblestatesethelper.hxx>
49 #include <unotools/accessiblerelationsethelper.hxx>
50 #include <vcl/svapp.hxx>
51 #include <vcl/menu.hxx>
53 #ifndef VCLEVENT_WINDOW_FRAMETITLECHANGED
54 #define VCLEVENT_WINDOW_FRAMETITLECHANGED 1018 // pData = XubString* = oldTitle
55 #endif
57 using namespace ::com::sun::star;
58 using namespace ::comphelper;
61 DBG_NAME(VCLXAccessibleComponent)
64 // ----------------------------------------------------
65 // class VCLXAccessibleComponent
66 // ----------------------------------------------------
67 VCLXAccessibleComponent::VCLXAccessibleComponent( VCLXWindow* pVCLXindow )
68 : AccessibleExtendedComponentHelper_BASE( new VCLExternalSolarLock() )
69 , OAccessibleImplementationAccess( )
71 DBG_CTOR( VCLXAccessibleComponent, 0 );
72 mpVCLXindow = pVCLXindow;
73 mxWindow = pVCLXindow;
75 m_pSolarLock = static_cast< VCLExternalSolarLock* >( getExternalLock( ) );
77 DBG_ASSERT( pVCLXindow->GetWindow(), "VCLXAccessibleComponent - no window!" );
78 if ( pVCLXindow->GetWindow() )
80 pVCLXindow->GetWindow()->AddEventListener( LINK( this, VCLXAccessibleComponent, WindowEventListener ) );
81 pVCLXindow->GetWindow()->AddChildEventListener( LINK( this, VCLXAccessibleComponent, WindowChildEventListener ) );
84 // announce the XAccessible of our creator to the base class
85 lateInit( pVCLXindow );
88 VCLXAccessibleComponent::~VCLXAccessibleComponent()
90 DBG_DTOR( VCLXAccessibleComponent, 0 );
92 ensureDisposed();
94 if ( mpVCLXindow && mpVCLXindow->GetWindow() )
96 mpVCLXindow->GetWindow()->RemoveEventListener( LINK( this, VCLXAccessibleComponent, WindowEventListener ) );
97 mpVCLXindow->GetWindow()->RemoveChildEventListener( LINK( this, VCLXAccessibleComponent, WindowChildEventListener ) );
100 delete m_pSolarLock;
101 m_pSolarLock = NULL;
102 // This is not completely safe. If we assume that the base class dtor calls some method which
103 // uses this lock, the we crash. However, as the base class' dtor does not have a chance to call _out_
104 // virtual methods, this is no problem as long as the base class is safe, i.e. does not use the external
105 // lock from within it's dtor. At the moment, we _know_ the base class is safe in this respect, so
106 // let's assume it keeps this way.
107 // @see OAccessibleContextHelper::OAccessibleContextHelper( IMutex* )
110 IMPLEMENT_FORWARD_XINTERFACE3( VCLXAccessibleComponent, AccessibleExtendedComponentHelper_BASE, OAccessibleImplementationAccess, VCLXAccessibleComponent_BASE )
111 IMPLEMENT_FORWARD_XTYPEPROVIDER3( VCLXAccessibleComponent, AccessibleExtendedComponentHelper_BASE, OAccessibleImplementationAccess, VCLXAccessibleComponent_BASE )
113 ::rtl::OUString VCLXAccessibleComponent::getImplementationName() throw (uno::RuntimeException)
115 return ::rtl::OUString::createFromAscii( "com.sun.star.comp.toolkit.AccessibleWindow" );
118 sal_Bool VCLXAccessibleComponent::supportsService( const ::rtl::OUString& rServiceName ) throw (uno::RuntimeException)
120 uno::Sequence< ::rtl::OUString > aNames( getSupportedServiceNames() );
121 const ::rtl::OUString* pNames = aNames.getConstArray();
122 const ::rtl::OUString* pEnd = pNames + aNames.getLength();
123 for ( ; pNames != pEnd && !pNames->equals( rServiceName ); ++pNames )
126 return pNames != pEnd;
129 uno::Sequence< ::rtl::OUString > VCLXAccessibleComponent::getSupportedServiceNames() throw (uno::RuntimeException)
131 uno::Sequence< ::rtl::OUString > aNames(1);
132 aNames[0] = ::rtl::OUString::createFromAscii( "com.sun.star.awt.AccessibleWindow" );
133 return aNames;
136 IMPL_LINK( VCLXAccessibleComponent, WindowEventListener, VclSimpleEvent*, pEvent )
138 DBG_CHKTHIS(VCLXAccessibleComponent,0);
140 DBG_ASSERT( pEvent && pEvent->ISA( VclWindowEvent ), "Unknown WindowEvent!" );
142 /* Ignore VCLEVENT_WINDOW_ENDPOPUPMODE, because the UNO accessibility wrapper
143 * might have been destroyed by the previous VCLEventListener (if no AT tool
144 * is running), e.g. sub-toolbars in impress.
146 if ( pEvent && pEvent->ISA( VclWindowEvent ) && mxWindow.is() /* #122218# */ && (pEvent->GetId() != VCLEVENT_WINDOW_ENDPOPUPMODE) )
148 DBG_ASSERT( ((VclWindowEvent*)pEvent)->GetWindow(), "Window???" );
149 if( !((VclWindowEvent*)pEvent)->GetWindow()->IsAccessibilityEventsSuppressed() || ( pEvent->GetId() == VCLEVENT_OBJECT_DYING ) )
151 ProcessWindowEvent( *(VclWindowEvent*)pEvent );
154 return 0;
157 IMPL_LINK( VCLXAccessibleComponent, WindowChildEventListener, VclSimpleEvent*, pEvent )
159 DBG_CHKTHIS(VCLXAccessibleComponent,0);
161 DBG_ASSERT( pEvent && pEvent->ISA( VclWindowEvent ), "Unknown WindowEvent!" );
162 if ( pEvent && pEvent->ISA( VclWindowEvent ) && mxWindow.is() /* #i68079# */ )
164 DBG_ASSERT( ((VclWindowEvent*)pEvent)->GetWindow(), "Window???" );
165 if( !((VclWindowEvent*)pEvent)->GetWindow()->IsAccessibilityEventsSuppressed() )
167 // #103087# to prevent an early release of the component
168 uno::Reference< accessibility::XAccessibleContext > xTmp = this;
170 ProcessWindowChildEvent( *(VclWindowEvent*)pEvent );
173 return 0;
176 uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::GetChildAccessible( const VclWindowEvent& rVclWindowEvent )
178 // checks if the data in the window event is our direct child
179 // and returns its accessible
181 // MT: Change this later, normaly a show/hide event shouldn't have the Window* in pData.
182 Window* pChildWindow = (Window *) rVclWindowEvent.GetData();
183 if( pChildWindow && GetWindow() == pChildWindow->GetAccessibleParentWindow() )
184 return pChildWindow->GetAccessible( rVclWindowEvent.GetId() == VCLEVENT_WINDOW_SHOW );
185 else
186 return uno::Reference< accessibility::XAccessible > ();
189 void VCLXAccessibleComponent::ProcessWindowChildEvent( const VclWindowEvent& rVclWindowEvent )
191 uno::Any aOldValue, aNewValue;
192 uno::Reference< accessibility::XAccessible > xAcc;
194 switch ( rVclWindowEvent.GetId() )
196 case VCLEVENT_WINDOW_SHOW: // send create on show for direct accessible children
198 xAcc = GetChildAccessible( rVclWindowEvent );
199 if( xAcc.is() )
201 aNewValue <<= xAcc;
202 NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
205 break;
206 case VCLEVENT_WINDOW_HIDE: // send destroy on hide for direct accessible children
208 xAcc = GetChildAccessible( rVclWindowEvent );
209 if( xAcc.is() )
211 aOldValue <<= xAcc;
212 NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
215 break;
219 void VCLXAccessibleComponent::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
221 uno::Any aOldValue, aNewValue;
223 Window* pAccWindow = rVclWindowEvent.GetWindow();
224 DBG_ASSERT( pAccWindow, "VCLXAccessibleComponent::ProcessWindowEvent - Window?" );
226 switch ( rVclWindowEvent.GetId() )
228 case VCLEVENT_OBJECT_DYING:
230 pAccWindow->RemoveEventListener( LINK( this, VCLXAccessibleComponent, WindowEventListener ) );
231 pAccWindow->RemoveChildEventListener( LINK( this, VCLXAccessibleComponent, WindowChildEventListener ) );
232 mxWindow.clear();
233 mpVCLXindow = NULL;
235 break;
237 // dont handle CHILDCREATED events here
238 // they are handled separately as child events, see ProcessWindowChildEvent above
241 case VCLEVENT_WINDOW_CHILDCREATED:
243 Window* pWindow = (Window*) rVclWindowEvent.GetData();
244 DBG_ASSERT( pWindow, "VCLEVENT_WINDOW_CHILDCREATED - Window=?" );
245 aNewValue <<= pWindow->GetAccessible();
246 NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
248 break;
250 case VCLEVENT_WINDOW_CHILDDESTROYED:
252 Window* pWindow = (Window*) rVclWindowEvent.GetData();
253 DBG_ASSERT( pWindow, "VCLEVENT_WINDOW_CHILDDESTROYED - Window=?" );
254 if ( pWindow->GetAccessible( FALSE ).is() )
256 aOldValue <<= pWindow->GetAccessible( FALSE );
257 NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
260 break;
263 // show and hide will be handled as child events only and are
264 // responsible for sending create/destroy events, see ProcessWindowChildEvent above
267 case VCLEVENT_WINDOW_SHOW:
269 aNewValue <<= accessibility::AccessibleStateType::VISIBLE;
270 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
272 aNewValue <<= accessibility::AccessibleStateType::SHOWING;
273 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
275 aNewValue.clear();
276 aOldValue <<= accessibility::AccessibleStateType::INVALID;
277 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
279 break;
280 case VCLEVENT_WINDOW_HIDE:
282 aOldValue <<= accessibility::AccessibleStateType::VISIBLE;
283 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
285 aOldValue <<= accessibility::AccessibleStateType::SHOWING;
286 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
288 aOldValue.clear();
289 aNewValue <<= accessibility::AccessibleStateType::INVALID;
290 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
292 break;
294 case VCLEVENT_WINDOW_ACTIVATE:
296 // avoid notification if a child frame is already active
297 // only one frame may be active at a given time
298 if ( !pAccWindow->HasActiveChildFrame() &&
299 ( getAccessibleRole() == accessibility::AccessibleRole::FRAME ||
300 getAccessibleRole() == accessibility::AccessibleRole::ALERT ||
301 getAccessibleRole() == accessibility::AccessibleRole::DIALOG ) ) // #i18891#
303 aNewValue <<= accessibility::AccessibleStateType::ACTIVE;
304 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
307 break;
308 case VCLEVENT_WINDOW_DEACTIVATE:
310 if ( getAccessibleRole() == accessibility::AccessibleRole::FRAME ||
311 getAccessibleRole() == accessibility::AccessibleRole::ALERT ||
312 getAccessibleRole() == accessibility::AccessibleRole::DIALOG ) // #i18891#
314 aOldValue <<= accessibility::AccessibleStateType::ACTIVE;
315 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
318 break;
319 case VCLEVENT_WINDOW_GETFOCUS:
320 case VCLEVENT_CONTROL_GETFOCUS:
322 if( (pAccWindow->IsCompoundControl() && rVclWindowEvent.GetId() == VCLEVENT_CONTROL_GETFOCUS) ||
323 (!pAccWindow->IsCompoundControl() && rVclWindowEvent.GetId() == VCLEVENT_WINDOW_GETFOCUS) )
325 // if multiple listeners were registered it is possible that the
326 // focus was changed during event processing (eg SfxTopWindow )
327 // #106082# allow ChildPathFocus only for CompoundControls, for windows the focus must be in the window itself
328 if( (pAccWindow->IsCompoundControl() && pAccWindow->HasChildPathFocus()) ||
329 (!pAccWindow->IsCompoundControl() && pAccWindow->HasFocus()) )
331 aNewValue <<= accessibility::AccessibleStateType::FOCUSED;
332 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
336 break;
337 case VCLEVENT_WINDOW_LOSEFOCUS:
338 case VCLEVENT_CONTROL_LOSEFOCUS:
340 if( (pAccWindow->IsCompoundControl() && rVclWindowEvent.GetId() == VCLEVENT_CONTROL_LOSEFOCUS) ||
341 (!pAccWindow->IsCompoundControl() && rVclWindowEvent.GetId() == VCLEVENT_WINDOW_LOSEFOCUS) )
343 aOldValue <<= accessibility::AccessibleStateType::FOCUSED;
344 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
347 break;
348 case VCLEVENT_WINDOW_FRAMETITLECHANGED:
350 ::rtl::OUString aOldName( *((::rtl::OUString*) rVclWindowEvent.GetData()) );
351 ::rtl::OUString aNewName( getAccessibleName() );
352 aOldValue <<= aOldName;
353 aNewValue <<= aNewName;
354 NotifyAccessibleEvent( accessibility::AccessibleEventId::NAME_CHANGED, aOldValue, aNewValue );
356 break;
357 case VCLEVENT_WINDOW_ENABLED:
359 aNewValue <<= accessibility::AccessibleStateType::ENABLED;
360 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
361 aNewValue <<= accessibility::AccessibleStateType::SENSITIVE;
362 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
364 break;
365 case VCLEVENT_WINDOW_DISABLED:
367 aOldValue <<= accessibility::AccessibleStateType::SENSITIVE;
368 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
370 aOldValue <<= accessibility::AccessibleStateType::ENABLED;
371 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
373 break;
374 case VCLEVENT_WINDOW_MOVE:
375 case VCLEVENT_WINDOW_RESIZE:
377 NotifyAccessibleEvent( accessibility::AccessibleEventId::BOUNDRECT_CHANGED, aOldValue, aNewValue );
379 break;
380 case VCLEVENT_WINDOW_MENUBARADDED:
382 MenuBar* pMenuBar = (MenuBar*) rVclWindowEvent.GetData();
383 if ( pMenuBar )
385 uno::Reference< accessibility::XAccessible > xChild( pMenuBar->GetAccessible() );
386 if ( xChild.is() )
388 aNewValue <<= xChild;
389 NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
393 break;
394 case VCLEVENT_WINDOW_MENUBARREMOVED:
396 MenuBar* pMenuBar = (MenuBar*) rVclWindowEvent.GetData();
397 if ( pMenuBar )
399 uno::Reference< accessibility::XAccessible > xChild( pMenuBar->GetAccessible() );
400 if ( xChild.is() )
402 aOldValue <<= xChild;
403 NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
407 break;
408 case VCLEVENT_WINDOW_MINIMIZE:
410 aNewValue <<= accessibility::AccessibleStateType::ICONIFIED;
411 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
413 break;
414 case VCLEVENT_WINDOW_NORMALIZE:
416 aOldValue <<= accessibility::AccessibleStateType::ICONIFIED;
417 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
419 break;
420 default:
423 break;
427 void VCLXAccessibleComponent::disposing()
429 if ( mpVCLXindow && mpVCLXindow->GetWindow() )
431 mpVCLXindow->GetWindow()->RemoveEventListener( LINK( this, VCLXAccessibleComponent, WindowEventListener ) );
432 mpVCLXindow->GetWindow()->RemoveChildEventListener( LINK( this, VCLXAccessibleComponent, WindowChildEventListener ) );
435 AccessibleExtendedComponentHelper_BASE::disposing();
437 mxWindow.clear();
438 mpVCLXindow = NULL;
441 Window* VCLXAccessibleComponent::GetWindow() const
443 return GetVCLXWindow() ? GetVCLXWindow()->GetWindow() : NULL;
446 void VCLXAccessibleComponent::FillAccessibleRelationSet( utl::AccessibleRelationSetHelper& rRelationSet )
448 Window* pWindow = GetWindow();
449 if ( pWindow )
451 Window *pLabeledBy = pWindow->GetLabeledBy();
452 if ( pLabeledBy && pLabeledBy != pWindow )
454 uno::Sequence< uno::Reference< uno::XInterface > > aSequence(1);
455 aSequence[0] = pLabeledBy->GetAccessible();
456 rRelationSet.AddRelation( accessibility::AccessibleRelation( accessibility::AccessibleRelationType::LABELED_BY, aSequence ) );
459 Window* pLabelFor = pWindow->GetLabelFor();
460 if ( pLabelFor && pLabelFor != pWindow )
462 uno::Sequence< uno::Reference< uno::XInterface > > aSequence(1);
463 aSequence[0] = pLabelFor->GetAccessible();
464 rRelationSet.AddRelation( accessibility::AccessibleRelation( accessibility::AccessibleRelationType::LABEL_FOR, aSequence ) );
469 void VCLXAccessibleComponent::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
471 Window* pWindow = GetWindow();
472 if ( pWindow )
474 if ( pWindow->IsVisible() )
476 rStateSet.AddState( accessibility::AccessibleStateType::VISIBLE );
477 rStateSet.AddState( accessibility::AccessibleStateType::SHOWING );
479 else
481 rStateSet.AddState( accessibility::AccessibleStateType::INVALID );
484 if ( pWindow->IsEnabled() )
486 rStateSet.AddState( accessibility::AccessibleStateType::ENABLED );
487 rStateSet.AddState( accessibility::AccessibleStateType::SENSITIVE );
490 if ( pWindow->HasChildPathFocus() &&
491 ( getAccessibleRole() == accessibility::AccessibleRole::FRAME ||
492 getAccessibleRole() == accessibility::AccessibleRole::ALERT ||
493 getAccessibleRole() == accessibility::AccessibleRole::DIALOG ) ) // #i18891#
494 rStateSet.AddState( accessibility::AccessibleStateType::ACTIVE );
496 Window* pChild = pWindow->GetWindow( WINDOW_FIRSTCHILD );
497 if ( ( !pWindow->IsCompoundControl() && pWindow->HasFocus() ) ||
498 ( pWindow->IsCompoundControl() && pChild && pChild->HasFocus() ) )
499 rStateSet.AddState( accessibility::AccessibleStateType::FOCUSED );
501 if ( pWindow->IsWait() )
502 rStateSet.AddState( accessibility::AccessibleStateType::BUSY );
504 if ( pWindow->GetStyle() & WB_SIZEABLE )
505 rStateSet.AddState( accessibility::AccessibleStateType::RESIZABLE );
507 if( pWindow->IsDialog() )
509 Dialog *pDlg = static_cast< Dialog* >( pWindow );
510 if( pDlg->IsInExecute() )
511 rStateSet.AddState( accessibility::AccessibleStateType::MODAL );
514 else
516 rStateSet.AddState( accessibility::AccessibleStateType::DEFUNC );
521 MUST BE SET FROM DERIVED CLASSES:
523 CHECKED
524 COLLAPSED
525 EXPANDED
526 EXPANDABLE
527 EDITABLE
528 FOCUSABLE
529 HORIZONTAL
530 VERTICAL
531 ICONIFIED
532 MULTILINE
533 MULTI_SELECTABLE
534 PRESSED
535 SELECTABLE
536 SELECTED
537 SINGLE_LINE
538 TRANSIENT
544 // accessibility::XAccessibleContext
545 sal_Int32 VCLXAccessibleComponent::getAccessibleChildCount() throw (uno::RuntimeException)
547 OExternalLockGuard aGuard( this );
549 sal_Int32 nChildren = 0;
550 if ( GetWindow() )
551 nChildren = GetWindow()->GetAccessibleChildWindowCount();
553 return nChildren;
556 uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::getAccessibleChild( sal_Int32 i ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
558 OExternalLockGuard aGuard( this );
560 if ( i >= getAccessibleChildCount() )
561 throw lang::IndexOutOfBoundsException();
563 uno::Reference< accessibility::XAccessible > xAcc;
564 if ( GetWindow() )
566 Window* pChild = GetWindow()->GetAccessibleChildWindow( (USHORT)i );
567 if ( pChild )
568 xAcc = pChild->GetAccessible();
571 return xAcc;
574 uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::getVclParent() const
576 uno::Reference< accessibility::XAccessible > xAcc;
577 if ( GetWindow() )
579 Window* pParent = GetWindow()->GetAccessibleParentWindow();
580 if ( pParent )
581 xAcc = pParent->GetAccessible();
583 return xAcc;
586 uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::getAccessibleParent( ) throw (uno::RuntimeException)
588 OExternalLockGuard aGuard( this );
590 uno::Reference< accessibility::XAccessible > xAcc( implGetForeignControlledParent() );
591 if ( !xAcc.is() )
592 // we do _not_ have a foreign-controlled parent -> default to our VCL parent
593 xAcc = getVclParent();
595 return xAcc;
598 sal_Int32 VCLXAccessibleComponent::getAccessibleIndexInParent( ) throw (uno::RuntimeException)
600 OExternalLockGuard aGuard( this );
602 sal_Int32 nIndex = -1;
604 uno::Reference< accessibility::XAccessible > xAcc( implGetForeignControlledParent() );
605 if ( xAcc.is() )
606 { // we _do_ have a foreign-controlled parent -> use the base class' implementation,
607 // which goes the UNO way
608 nIndex = AccessibleExtendedComponentHelper_BASE::getAccessibleIndexInParent( );
610 else
612 if ( GetWindow() )
614 Window* pParent = GetWindow()->GetAccessibleParentWindow();
615 if ( pParent )
618 for ( USHORT n = pParent->GetAccessibleChildWindowCount(); n; )
620 Window* pChild = pParent->GetAccessibleChildWindow( --n );
621 if ( pChild == GetWindow() )
623 nIndex = n;
624 break;
628 // Iterate over all the parent's children and search for this object.
629 // this should be compatible with the code in SVX
630 uno::Reference< accessibility::XAccessible > xParentAcc( pParent->GetAccessible() );
631 if ( xParentAcc.is() )
633 uno::Reference< accessibility::XAccessibleContext > xParentContext ( xParentAcc->getAccessibleContext() );
634 if ( xParentContext.is() )
636 sal_Int32 nChildCount = xParentContext->getAccessibleChildCount();
637 for ( sal_Int32 i=0; i<nChildCount; i++ )
639 uno::Reference< accessibility::XAccessible > xChild( xParentContext->getAccessibleChild(i) );
640 if ( xChild.is() )
642 uno::Reference< accessibility::XAccessibleContext > xChildContext = xChild->getAccessibleContext();
643 if ( xChildContext == (accessibility::XAccessibleContext*) this )
645 nIndex = i;
646 break;
655 return nIndex;
658 sal_Int16 VCLXAccessibleComponent::getAccessibleRole( ) throw (uno::RuntimeException)
660 OExternalLockGuard aGuard( this );
662 sal_Int16 nRole = 0;
664 if ( GetWindow() )
665 nRole = GetWindow()->GetAccessibleRole();
667 return nRole;
670 ::rtl::OUString VCLXAccessibleComponent::getAccessibleDescription( ) throw (uno::RuntimeException)
672 OExternalLockGuard aGuard( this );
674 ::rtl::OUString aDescription;
676 if ( GetWindow() )
677 aDescription = GetWindow()->GetAccessibleDescription();
679 return aDescription;
682 ::rtl::OUString VCLXAccessibleComponent::getAccessibleName( ) throw (uno::RuntimeException)
684 OExternalLockGuard aGuard( this );
686 ::rtl::OUString aName;
687 if ( GetWindow() )
689 aName = GetWindow()->GetAccessibleName();
690 #if OSL_DEBUG_LEVEL > 1
691 aName += String( RTL_CONSTASCII_USTRINGPARAM( " (Type = " ) );
692 aName += String::CreateFromInt32( GetWindow()->GetType() );
693 aName += String( RTL_CONSTASCII_USTRINGPARAM( ")" ) );
694 #endif
696 return aName;
699 uno::Reference< accessibility::XAccessibleRelationSet > VCLXAccessibleComponent::getAccessibleRelationSet( ) throw (uno::RuntimeException)
701 OExternalLockGuard aGuard( this );
703 utl::AccessibleRelationSetHelper* pRelationSetHelper = new utl::AccessibleRelationSetHelper;
704 uno::Reference< accessibility::XAccessibleRelationSet > xSet = pRelationSetHelper;
705 FillAccessibleRelationSet( *pRelationSetHelper );
706 return xSet;
709 uno::Reference< accessibility::XAccessibleStateSet > VCLXAccessibleComponent::getAccessibleStateSet( ) throw (uno::RuntimeException)
711 OExternalLockGuard aGuard( this );
713 utl::AccessibleStateSetHelper* pStateSetHelper = new utl::AccessibleStateSetHelper;
714 uno::Reference< accessibility::XAccessibleStateSet > xSet = pStateSetHelper;
715 FillAccessibleStateSet( *pStateSetHelper );
716 return xSet;
719 lang::Locale VCLXAccessibleComponent::getLocale() throw (accessibility::IllegalAccessibleComponentStateException, uno::RuntimeException)
721 OExternalLockGuard aGuard( this );
723 return Application::GetSettings().GetLocale();
726 uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::getAccessibleAtPoint( const awt::Point& rPoint ) throw (uno::RuntimeException)
728 OExternalLockGuard aGuard( this );
730 uno::Reference< accessibility::XAccessible > xChild;
731 for ( sal_uInt32 i = 0, nCount = getAccessibleChildCount(); i < nCount; ++i )
733 uno::Reference< accessibility::XAccessible > xAcc = getAccessibleChild( i );
734 if ( xAcc.is() )
736 uno::Reference< accessibility::XAccessibleComponent > xComp( xAcc->getAccessibleContext(), uno::UNO_QUERY );
737 if ( xComp.is() )
739 Rectangle aRect = VCLRectangle( xComp->getBounds() );
740 Point aPos = VCLPoint( rPoint );
741 if ( aRect.IsInside( aPos ) )
743 xChild = xAcc;
744 break;
750 return xChild;
753 // accessibility::XAccessibleComponent
754 awt::Rectangle VCLXAccessibleComponent::implGetBounds() throw (uno::RuntimeException)
756 awt::Rectangle aBounds ( 0, 0, 0, 0 );
758 Window* pWindow = GetWindow();
759 if ( pWindow )
761 Rectangle aRect = pWindow->GetWindowExtentsRelative( NULL );
762 aBounds = AWTRectangle( aRect );
763 Window* pParent = pWindow->GetAccessibleParentWindow();
764 if ( pParent )
766 Rectangle aParentRect = pParent->GetWindowExtentsRelative( NULL );
767 awt::Point aParentScreenLoc = AWTPoint( aParentRect.TopLeft() );
768 aBounds.X -= aParentScreenLoc.X;
769 aBounds.Y -= aParentScreenLoc.Y;
773 uno::Reference< accessibility::XAccessible > xParent( implGetForeignControlledParent() );
774 if ( xParent.is() )
775 { // hmm, we can't rely on our VCL coordinates, as in the Accessibility Hierarchy, somebody gave
776 // us a parent which is different from our VCL parent
777 // (actually, we did not check if it's really different ...)
779 // the screen location of the foreign parent
780 uno::Reference< accessibility::XAccessibleComponent > xParentComponent( xParent->getAccessibleContext(), uno::UNO_QUERY );
781 DBG_ASSERT( xParentComponent.is(), "VCLXAccessibleComponent::implGetBounds: invalid (foreign) parent component!" );
783 awt::Point aScreenLocForeign( 0, 0 );
784 if ( xParentComponent.is() )
785 aScreenLocForeign = xParentComponent->getLocationOnScreen();
787 // the screen location of the VCL parent
788 xParent = getVclParent();
789 if ( xParent.is() )
790 xParentComponent = xParentComponent.query( xParent->getAccessibleContext() );
792 awt::Point aScreenLocVCL( 0, 0 );
793 if ( xParentComponent.is() )
794 aScreenLocVCL = xParentComponent->getLocationOnScreen();
796 // the difference between them
797 awt::Size aOffset( aScreenLocVCL.X - aScreenLocForeign.X, aScreenLocVCL.Y - aScreenLocForeign.Y );
798 // move the bounds
799 aBounds.X += aOffset.Width;
800 aBounds.Y += aOffset.Height;
803 return aBounds;
806 awt::Point VCLXAccessibleComponent::getLocationOnScreen( ) throw (uno::RuntimeException)
808 OExternalLockGuard aGuard( this );
810 awt::Point aPos;
811 if ( GetWindow() )
813 Rectangle aRect = GetWindow()->GetWindowExtentsRelative( NULL );
814 aPos.X = aRect.Left();
815 aPos.Y = aRect.Top();
818 return aPos;
821 void VCLXAccessibleComponent::grabFocus( ) throw (uno::RuntimeException)
823 OExternalLockGuard aGuard( this );
825 uno::Reference< accessibility::XAccessibleStateSet > xStates = getAccessibleStateSet();
826 if ( mxWindow.is() && xStates.is() && xStates->contains( accessibility::AccessibleStateType::FOCUSABLE ) )
827 mxWindow->setFocus();
830 sal_Int32 SAL_CALL VCLXAccessibleComponent::getForeground( ) throw (uno::RuntimeException)
832 OExternalLockGuard aGuard( this );
834 sal_Int32 nColor = 0;
835 Window* pWindow = GetWindow();
836 if ( pWindow )
838 if ( pWindow->IsControlForeground() )
839 nColor = pWindow->GetControlForeground().GetColor();
840 else
842 Font aFont;
843 if ( pWindow->IsControlFont() )
844 aFont = pWindow->GetControlFont();
845 else
846 aFont = pWindow->GetFont();
847 nColor = aFont.GetColor().GetColor();
851 return nColor;
854 sal_Int32 SAL_CALL VCLXAccessibleComponent::getBackground( ) throw (uno::RuntimeException)
856 OExternalLockGuard aGuard( this );
858 sal_Int32 nColor = 0;
859 Window* pWindow = GetWindow();
860 if ( pWindow )
862 if ( pWindow->IsControlBackground() )
863 nColor = pWindow->GetControlBackground().GetColor();
864 else
865 nColor = pWindow->GetBackground().GetColor().GetColor();
868 return nColor;
871 // XAccessibleExtendedComponent
873 uno::Reference< awt::XFont > SAL_CALL VCLXAccessibleComponent::getFont( ) throw (uno::RuntimeException)
875 OExternalLockGuard aGuard( this );
877 uno::Reference< awt::XFont > xFont;
878 Window* pWindow = GetWindow();
879 if ( pWindow )
881 uno::Reference< awt::XDevice > xDev( pWindow->GetComponentInterface(), uno::UNO_QUERY );
882 if ( xDev.is() )
884 Font aFont;
885 if ( pWindow->IsControlFont() )
886 aFont = pWindow->GetControlFont();
887 else
888 aFont = pWindow->GetFont();
889 VCLXFont* pVCLXFont = new VCLXFont;
890 pVCLXFont->Init( *xDev.get(), aFont );
891 xFont = pVCLXFont;
895 return xFont;
898 ::rtl::OUString SAL_CALL VCLXAccessibleComponent::getTitledBorderText( ) throw (uno::RuntimeException)
900 OExternalLockGuard aGuard( this );
902 ::rtl::OUString sRet;
903 if ( GetWindow() )
904 sRet = GetWindow()->GetText();
906 return sRet;
909 ::rtl::OUString SAL_CALL VCLXAccessibleComponent::getToolTipText( ) throw (uno::RuntimeException)
911 OExternalLockGuard aGuard( this );
913 ::rtl::OUString sRet;
914 if ( GetWindow() )
915 sRet = GetWindow()->GetQuickHelpText();
917 return sRet;