Version 4.0.2.1, tag libreoffice-4.0.2.1
[LibreOffice.git] / toolkit / source / awt / vclxaccessiblecomponent.cxx
blob106cb081047490b60b6736a25d90e08a2e476c1c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/accessibility/AccessibleRole.hpp>
21 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
22 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
23 #include <com/sun/star/accessibility/XAccessibleEventListener.hpp>
24 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
25 #include <toolkit/awt/vclxaccessiblecomponent.hxx>
26 #include <toolkit/helper/externallock.hxx>
27 #include <toolkit/awt/vclxwindow.hxx>
28 #include <toolkit/helper/convert.hxx>
29 #include <toolkit/awt/vclxfont.hxx>
30 #include <vcl/dialog.hxx>
31 #include <vcl/window.hxx>
32 #include <tools/debug.hxx>
33 #include <unotools/accessiblestatesethelper.hxx>
34 #include <unotools/accessiblerelationsethelper.hxx>
35 #include <vcl/svapp.hxx>
36 #include <vcl/menu.hxx>
38 #ifndef VCLEVENT_WINDOW_FRAMETITLECHANGED
39 #define VCLEVENT_WINDOW_FRAMETITLECHANGED 1018 // pData = XubString* = oldTitle
40 #endif
42 using namespace ::com::sun::star;
43 using namespace ::comphelper;
46 DBG_NAME(VCLXAccessibleComponent)
49 // ----------------------------------------------------
50 // class VCLXAccessibleComponent
51 // ----------------------------------------------------
52 VCLXAccessibleComponent::VCLXAccessibleComponent( VCLXWindow* pVCLXindow )
53 : AccessibleExtendedComponentHelper_BASE( new VCLExternalSolarLock() )
54 , OAccessibleImplementationAccess( )
56 DBG_CTOR( VCLXAccessibleComponent, 0 );
57 mpVCLXindow = pVCLXindow;
58 mxWindow = pVCLXindow;
60 m_pSolarLock = static_cast< VCLExternalSolarLock* >( getExternalLock( ) );
62 DBG_ASSERT( pVCLXindow->GetWindow(), "VCLXAccessibleComponent - no window!" );
63 if ( pVCLXindow->GetWindow() )
65 pVCLXindow->GetWindow()->AddEventListener( LINK( this, VCLXAccessibleComponent, WindowEventListener ) );
66 pVCLXindow->GetWindow()->AddChildEventListener( LINK( this, VCLXAccessibleComponent, WindowChildEventListener ) );
69 // announce the XAccessible of our creator to the base class
70 lateInit( pVCLXindow );
73 VCLXAccessibleComponent::~VCLXAccessibleComponent()
75 DBG_DTOR( VCLXAccessibleComponent, 0 );
77 ensureDisposed();
79 if ( mpVCLXindow && mpVCLXindow->GetWindow() )
81 mpVCLXindow->GetWindow()->RemoveEventListener( LINK( this, VCLXAccessibleComponent, WindowEventListener ) );
82 mpVCLXindow->GetWindow()->RemoveChildEventListener( LINK( this, VCLXAccessibleComponent, WindowChildEventListener ) );
85 delete m_pSolarLock;
86 m_pSolarLock = NULL;
87 // This is not completely safe. If we assume that the base class dtor calls some method which
88 // uses this lock, the we crash. However, as the base class' dtor does not have a chance to call _out_
89 // virtual methods, this is no problem as long as the base class is safe, i.e. does not use the external
90 // lock from within it's dtor. At the moment, we _know_ the base class is safe in this respect, so
91 // let's assume it keeps this way.
92 // @see OAccessibleContextHelper::OAccessibleContextHelper( IMutex* )
95 IMPLEMENT_FORWARD_XINTERFACE3( VCLXAccessibleComponent, AccessibleExtendedComponentHelper_BASE, OAccessibleImplementationAccess, VCLXAccessibleComponent_BASE )
96 IMPLEMENT_FORWARD_XTYPEPROVIDER3( VCLXAccessibleComponent, AccessibleExtendedComponentHelper_BASE, OAccessibleImplementationAccess, VCLXAccessibleComponent_BASE )
98 ::rtl::OUString VCLXAccessibleComponent::getImplementationName() throw (uno::RuntimeException)
100 return ::rtl::OUString("com.sun.star.comp.toolkit.AccessibleWindow");
103 sal_Bool VCLXAccessibleComponent::supportsService( const ::rtl::OUString& rServiceName ) throw (uno::RuntimeException)
105 uno::Sequence< ::rtl::OUString > aNames( getSupportedServiceNames() );
106 const ::rtl::OUString* pNames = aNames.getConstArray();
107 const ::rtl::OUString* pEnd = pNames + aNames.getLength();
108 for ( ; pNames != pEnd && !pNames->equals( rServiceName ); ++pNames )
111 return pNames != pEnd;
114 uno::Sequence< ::rtl::OUString > VCLXAccessibleComponent::getSupportedServiceNames() throw (uno::RuntimeException)
116 uno::Sequence< ::rtl::OUString > aNames(1);
117 aNames[0] = ::rtl::OUString("com.sun.star.awt.AccessibleWindow");
118 return aNames;
121 IMPL_LINK( VCLXAccessibleComponent, WindowEventListener, VclSimpleEvent*, pEvent )
123 DBG_CHKTHIS(VCLXAccessibleComponent,0);
125 DBG_ASSERT( pEvent && pEvent->ISA( VclWindowEvent ), "Unknown WindowEvent!" );
127 /* Ignore VCLEVENT_WINDOW_ENDPOPUPMODE, because the UNO accessibility wrapper
128 * might have been destroyed by the previous VCLEventListener (if no AT tool
129 * is running), e.g. sub-toolbars in impress.
131 if ( pEvent && pEvent->ISA( VclWindowEvent ) && mxWindow.is() /* #122218# */ && (pEvent->GetId() != VCLEVENT_WINDOW_ENDPOPUPMODE) )
133 DBG_ASSERT( ((VclWindowEvent*)pEvent)->GetWindow(), "Window???" );
134 if( !((VclWindowEvent*)pEvent)->GetWindow()->IsAccessibilityEventsSuppressed() || ( pEvent->GetId() == VCLEVENT_OBJECT_DYING ) )
136 ProcessWindowEvent( *(VclWindowEvent*)pEvent );
139 return 0;
142 IMPL_LINK( VCLXAccessibleComponent, WindowChildEventListener, VclSimpleEvent*, pEvent )
144 DBG_CHKTHIS(VCLXAccessibleComponent,0);
146 DBG_ASSERT( pEvent && pEvent->ISA( VclWindowEvent ), "Unknown WindowEvent!" );
147 if ( pEvent && pEvent->ISA( VclWindowEvent ) && mxWindow.is() /* #i68079# */ )
149 DBG_ASSERT( ((VclWindowEvent*)pEvent)->GetWindow(), "Window???" );
150 if( !((VclWindowEvent*)pEvent)->GetWindow()->IsAccessibilityEventsSuppressed() )
152 // #103087# to prevent an early release of the component
153 uno::Reference< accessibility::XAccessibleContext > xTmp = this;
155 ProcessWindowChildEvent( *(VclWindowEvent*)pEvent );
158 return 0;
161 uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::GetChildAccessible( const VclWindowEvent& rVclWindowEvent )
163 // checks if the data in the window event is our direct child
164 // and returns its accessible
166 // MT: Change this later, normaly a show/hide event shouldn't have the Window* in pData.
167 Window* pChildWindow = (Window *) rVclWindowEvent.GetData();
168 if( pChildWindow && GetWindow() == pChildWindow->GetAccessibleParentWindow() )
169 return pChildWindow->GetAccessible( rVclWindowEvent.GetId() == VCLEVENT_WINDOW_SHOW );
170 else
171 return uno::Reference< accessibility::XAccessible > ();
174 void VCLXAccessibleComponent::ProcessWindowChildEvent( const VclWindowEvent& rVclWindowEvent )
176 uno::Any aOldValue, aNewValue;
177 uno::Reference< accessibility::XAccessible > xAcc;
179 switch ( rVclWindowEvent.GetId() )
181 case VCLEVENT_WINDOW_SHOW: // send create on show for direct accessible children
183 xAcc = GetChildAccessible( rVclWindowEvent );
184 if( xAcc.is() )
186 aNewValue <<= xAcc;
187 NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
190 break;
191 case VCLEVENT_WINDOW_HIDE: // send destroy on hide for direct accessible children
193 xAcc = GetChildAccessible( rVclWindowEvent );
194 if( xAcc.is() )
196 aOldValue <<= xAcc;
197 NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
200 break;
204 void VCLXAccessibleComponent::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
206 uno::Any aOldValue, aNewValue;
208 Window* pAccWindow = rVclWindowEvent.GetWindow();
209 DBG_ASSERT( pAccWindow, "VCLXAccessibleComponent::ProcessWindowEvent - Window?" );
211 switch ( rVclWindowEvent.GetId() )
213 case VCLEVENT_OBJECT_DYING:
215 pAccWindow->RemoveEventListener( LINK( this, VCLXAccessibleComponent, WindowEventListener ) );
216 pAccWindow->RemoveChildEventListener( LINK( this, VCLXAccessibleComponent, WindowChildEventListener ) );
217 mxWindow.clear();
218 mpVCLXindow = NULL;
220 break;
222 // dont handle CHILDCREATED events here
223 // they are handled separately as child events, see ProcessWindowChildEvent above
226 case VCLEVENT_WINDOW_CHILDCREATED:
228 Window* pWindow = (Window*) rVclWindowEvent.GetData();
229 DBG_ASSERT( pWindow, "VCLEVENT_WINDOW_CHILDCREATED - Window=?" );
230 aNewValue <<= pWindow->GetAccessible();
231 NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
233 break;
235 case VCLEVENT_WINDOW_CHILDDESTROYED:
237 Window* pWindow = (Window*) rVclWindowEvent.GetData();
238 DBG_ASSERT( pWindow, "VCLEVENT_WINDOW_CHILDDESTROYED - Window=?" );
239 if ( pWindow->GetAccessible( sal_False ).is() )
241 aOldValue <<= pWindow->GetAccessible( sal_False );
242 NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
245 break;
248 // show and hide will be handled as child events only and are
249 // responsible for sending create/destroy events, see ProcessWindowChildEvent above
252 case VCLEVENT_WINDOW_SHOW:
254 aNewValue <<= accessibility::AccessibleStateType::VISIBLE;
255 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
257 aNewValue <<= accessibility::AccessibleStateType::SHOWING;
258 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
260 aNewValue.clear();
261 aOldValue <<= accessibility::AccessibleStateType::INVALID;
262 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
264 break;
265 case VCLEVENT_WINDOW_HIDE:
267 aOldValue <<= accessibility::AccessibleStateType::VISIBLE;
268 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
270 aOldValue <<= accessibility::AccessibleStateType::SHOWING;
271 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
273 aOldValue.clear();
274 aNewValue <<= accessibility::AccessibleStateType::INVALID;
275 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
277 break;
279 case VCLEVENT_WINDOW_ACTIVATE:
281 // avoid notification if a child frame is already active
282 // only one frame may be active at a given time
283 if ( !pAccWindow->HasActiveChildFrame() &&
284 ( getAccessibleRole() == accessibility::AccessibleRole::FRAME ||
285 getAccessibleRole() == accessibility::AccessibleRole::ALERT ||
286 getAccessibleRole() == accessibility::AccessibleRole::DIALOG ) ) // #i18891#
288 aNewValue <<= accessibility::AccessibleStateType::ACTIVE;
289 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
292 break;
293 case VCLEVENT_WINDOW_DEACTIVATE:
295 if ( getAccessibleRole() == accessibility::AccessibleRole::FRAME ||
296 getAccessibleRole() == accessibility::AccessibleRole::ALERT ||
297 getAccessibleRole() == accessibility::AccessibleRole::DIALOG ) // #i18891#
299 aOldValue <<= accessibility::AccessibleStateType::ACTIVE;
300 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
303 break;
304 case VCLEVENT_WINDOW_GETFOCUS:
305 case VCLEVENT_CONTROL_GETFOCUS:
307 if( (pAccWindow->IsCompoundControl() && rVclWindowEvent.GetId() == VCLEVENT_CONTROL_GETFOCUS) ||
308 (!pAccWindow->IsCompoundControl() && rVclWindowEvent.GetId() == VCLEVENT_WINDOW_GETFOCUS) )
310 // if multiple listeners were registered it is possible that the
311 // focus was changed during event processing (eg SfxTopWindow )
312 // #106082# allow ChildPathFocus only for CompoundControls, for windows the focus must be in the window itself
313 if( (pAccWindow->IsCompoundControl() && pAccWindow->HasChildPathFocus()) ||
314 (!pAccWindow->IsCompoundControl() && pAccWindow->HasFocus()) )
316 aNewValue <<= accessibility::AccessibleStateType::FOCUSED;
317 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
321 break;
322 case VCLEVENT_WINDOW_LOSEFOCUS:
323 case VCLEVENT_CONTROL_LOSEFOCUS:
325 if( (pAccWindow->IsCompoundControl() && rVclWindowEvent.GetId() == VCLEVENT_CONTROL_LOSEFOCUS) ||
326 (!pAccWindow->IsCompoundControl() && rVclWindowEvent.GetId() == VCLEVENT_WINDOW_LOSEFOCUS) )
328 aOldValue <<= accessibility::AccessibleStateType::FOCUSED;
329 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
332 break;
333 case VCLEVENT_WINDOW_FRAMETITLECHANGED:
335 ::rtl::OUString aOldName( *((::rtl::OUString*) rVclWindowEvent.GetData()) );
336 ::rtl::OUString aNewName( getAccessibleName() );
337 aOldValue <<= aOldName;
338 aNewValue <<= aNewName;
339 NotifyAccessibleEvent( accessibility::AccessibleEventId::NAME_CHANGED, aOldValue, aNewValue );
341 break;
342 case VCLEVENT_WINDOW_ENABLED:
344 aNewValue <<= accessibility::AccessibleStateType::ENABLED;
345 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
346 aNewValue <<= accessibility::AccessibleStateType::SENSITIVE;
347 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
349 break;
350 case VCLEVENT_WINDOW_DISABLED:
352 aOldValue <<= accessibility::AccessibleStateType::SENSITIVE;
353 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
355 aOldValue <<= accessibility::AccessibleStateType::ENABLED;
356 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
358 break;
359 case VCLEVENT_WINDOW_MOVE:
360 case VCLEVENT_WINDOW_RESIZE:
362 NotifyAccessibleEvent( accessibility::AccessibleEventId::BOUNDRECT_CHANGED, aOldValue, aNewValue );
364 break;
365 case VCLEVENT_WINDOW_MENUBARADDED:
367 MenuBar* pMenuBar = (MenuBar*) rVclWindowEvent.GetData();
368 if ( pMenuBar )
370 uno::Reference< accessibility::XAccessible > xChild( pMenuBar->GetAccessible() );
371 if ( xChild.is() )
373 aNewValue <<= xChild;
374 NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
378 break;
379 case VCLEVENT_WINDOW_MENUBARREMOVED:
381 MenuBar* pMenuBar = (MenuBar*) rVclWindowEvent.GetData();
382 if ( pMenuBar )
384 uno::Reference< accessibility::XAccessible > xChild( pMenuBar->GetAccessible() );
385 if ( xChild.is() )
387 aOldValue <<= xChild;
388 NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
392 break;
393 case VCLEVENT_WINDOW_MINIMIZE:
395 aNewValue <<= accessibility::AccessibleStateType::ICONIFIED;
396 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
398 break;
399 case VCLEVENT_WINDOW_NORMALIZE:
401 aOldValue <<= accessibility::AccessibleStateType::ICONIFIED;
402 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
404 break;
405 default:
408 break;
412 void VCLXAccessibleComponent::disposing()
414 if ( mpVCLXindow && mpVCLXindow->GetWindow() )
416 mpVCLXindow->GetWindow()->RemoveEventListener( LINK( this, VCLXAccessibleComponent, WindowEventListener ) );
417 mpVCLXindow->GetWindow()->RemoveChildEventListener( LINK( this, VCLXAccessibleComponent, WindowChildEventListener ) );
420 AccessibleExtendedComponentHelper_BASE::disposing();
422 mxWindow.clear();
423 mpVCLXindow = NULL;
426 Window* VCLXAccessibleComponent::GetWindow() const
428 return GetVCLXWindow() ? GetVCLXWindow()->GetWindow() : NULL;
431 void VCLXAccessibleComponent::FillAccessibleRelationSet( utl::AccessibleRelationSetHelper& rRelationSet )
433 Window* pWindow = GetWindow();
434 if ( pWindow )
436 Window *pLabeledBy = pWindow->GetAccessibleRelationLabeledBy();
437 if ( pLabeledBy && pLabeledBy != pWindow )
439 uno::Sequence< uno::Reference< uno::XInterface > > aSequence(1);
440 aSequence[0] = pLabeledBy->GetAccessible();
441 rRelationSet.AddRelation( accessibility::AccessibleRelation( accessibility::AccessibleRelationType::LABELED_BY, aSequence ) );
444 Window* pLabelFor = pWindow->GetAccessibleRelationLabelFor();
445 if ( pLabelFor && pLabelFor != pWindow )
447 uno::Sequence< uno::Reference< uno::XInterface > > aSequence(1);
448 aSequence[0] = pLabelFor->GetAccessible();
449 rRelationSet.AddRelation( accessibility::AccessibleRelation( accessibility::AccessibleRelationType::LABEL_FOR, aSequence ) );
454 void VCLXAccessibleComponent::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
456 Window* pWindow = GetWindow();
457 if ( pWindow )
459 if ( pWindow->IsVisible() )
461 rStateSet.AddState( accessibility::AccessibleStateType::VISIBLE );
462 rStateSet.AddState( accessibility::AccessibleStateType::SHOWING );
464 else
466 rStateSet.AddState( accessibility::AccessibleStateType::INVALID );
469 if ( pWindow->IsEnabled() )
471 rStateSet.AddState( accessibility::AccessibleStateType::ENABLED );
472 rStateSet.AddState( accessibility::AccessibleStateType::SENSITIVE );
475 if ( pWindow->HasChildPathFocus() &&
476 ( getAccessibleRole() == accessibility::AccessibleRole::FRAME ||
477 getAccessibleRole() == accessibility::AccessibleRole::ALERT ||
478 getAccessibleRole() == accessibility::AccessibleRole::DIALOG ) ) // #i18891#
479 rStateSet.AddState( accessibility::AccessibleStateType::ACTIVE );
481 // #104290# MT: This way, a ComboBox doesn't get state FOCUSED.
482 // I also don't understand
483 // a) why WINDOW_FIRSTCHILD is used here (which btw is a border window in the case of a combo box)
484 // b) why HasFocus() is nout "enough" for a compound control
486 Window* pChild = pWindow->GetWindow( WINDOW_FIRSTCHILD );
487 if ( ( !pWindow->IsCompoundControl() && pWindow->HasFocus() ) ||
488 ( pWindow->IsCompoundControl() && pChild && pChild->HasFocus() ) )
489 rStateSet.AddState( accessibility::AccessibleStateType::FOCUSED );
491 if ( pWindow->HasFocus() || ( pWindow->IsCompoundControl() && pWindow->HasChildPathFocus() ) )
492 rStateSet.AddState( accessibility::AccessibleStateType::FOCUSED );
494 if ( pWindow->IsWait() )
495 rStateSet.AddState( accessibility::AccessibleStateType::BUSY );
497 if ( pWindow->GetStyle() & WB_SIZEABLE )
498 rStateSet.AddState( accessibility::AccessibleStateType::RESIZABLE );
500 if( pWindow->IsDialog() )
502 Dialog *pDlg = static_cast< Dialog* >( pWindow );
503 if( pDlg->IsInExecute() )
504 rStateSet.AddState( accessibility::AccessibleStateType::MODAL );
507 else
509 rStateSet.AddState( accessibility::AccessibleStateType::DEFUNC );
514 MUST BE SET FROM DERIVED CLASSES:
516 CHECKED
517 COLLAPSED
518 EXPANDED
519 EXPANDABLE
520 EDITABLE
521 FOCUSABLE
522 HORIZONTAL
523 VERTICAL
524 ICONIFIED
525 MULTILINE
526 MULTI_SELECTABLE
527 PRESSED
528 SELECTABLE
529 SELECTED
530 SINGLE_LINE
531 TRANSIENT
537 // accessibility::XAccessibleContext
538 sal_Int32 VCLXAccessibleComponent::getAccessibleChildCount() throw (uno::RuntimeException)
540 OExternalLockGuard aGuard( this );
542 sal_Int32 nChildren = 0;
543 if ( GetWindow() )
544 nChildren = GetWindow()->GetAccessibleChildWindowCount();
546 return nChildren;
549 uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::getAccessibleChild( sal_Int32 i ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
551 OExternalLockGuard aGuard( this );
553 if ( i >= getAccessibleChildCount() )
554 throw lang::IndexOutOfBoundsException();
556 uno::Reference< accessibility::XAccessible > xAcc;
557 if ( GetWindow() )
559 Window* pChild = GetWindow()->GetAccessibleChildWindow( (sal_uInt16)i );
560 if ( pChild )
561 xAcc = pChild->GetAccessible();
564 return xAcc;
567 uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::getVclParent() const
569 uno::Reference< accessibility::XAccessible > xAcc;
570 if ( GetWindow() )
572 Window* pParent = GetWindow()->GetAccessibleParentWindow();
573 if ( pParent )
574 xAcc = pParent->GetAccessible();
576 return xAcc;
579 uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::getAccessibleParent( ) throw (uno::RuntimeException)
581 OExternalLockGuard aGuard( this );
583 uno::Reference< accessibility::XAccessible > xAcc( implGetForeignControlledParent() );
584 if ( !xAcc.is() )
585 // we do _not_ have a foreign-controlled parent -> default to our VCL parent
586 xAcc = getVclParent();
588 return xAcc;
591 sal_Int32 VCLXAccessibleComponent::getAccessibleIndexInParent( ) throw (uno::RuntimeException)
593 OExternalLockGuard aGuard( this );
595 sal_Int32 nIndex = -1;
597 uno::Reference< accessibility::XAccessible > xAcc( implGetForeignControlledParent() );
598 if ( xAcc.is() )
599 { // we _do_ have a foreign-controlled parent -> use the base class' implementation,
600 // which goes the UNO way
601 nIndex = AccessibleExtendedComponentHelper_BASE::getAccessibleIndexInParent( );
603 else
605 if ( GetWindow() )
607 Window* pParent = GetWindow()->GetAccessibleParentWindow();
608 if ( pParent )
611 for ( sal_uInt16 n = pParent->GetAccessibleChildWindowCount(); n; )
613 Window* pChild = pParent->GetAccessibleChildWindow( --n );
614 if ( pChild == GetWindow() )
616 nIndex = n;
617 break;
621 // Iterate over all the parent's children and search for this object.
622 // this should be compatible with the code in SVX
623 uno::Reference< accessibility::XAccessible > xParentAcc( pParent->GetAccessible() );
624 if ( xParentAcc.is() )
626 uno::Reference< accessibility::XAccessibleContext > xParentContext ( xParentAcc->getAccessibleContext() );
627 if ( xParentContext.is() )
629 sal_Int32 nChildCount = xParentContext->getAccessibleChildCount();
630 for ( sal_Int32 i=0; i<nChildCount; i++ )
632 uno::Reference< accessibility::XAccessible > xChild( xParentContext->getAccessibleChild(i) );
633 if ( xChild.is() )
635 uno::Reference< accessibility::XAccessibleContext > xChildContext = xChild->getAccessibleContext();
636 if ( xChildContext == (accessibility::XAccessibleContext*) this )
638 nIndex = i;
639 break;
648 return nIndex;
651 sal_Int16 VCLXAccessibleComponent::getAccessibleRole( ) throw (uno::RuntimeException)
653 OExternalLockGuard aGuard( this );
655 sal_Int16 nRole = 0;
657 if ( GetWindow() )
658 nRole = GetWindow()->GetAccessibleRole();
660 return nRole;
663 ::rtl::OUString VCLXAccessibleComponent::getAccessibleDescription( ) throw (uno::RuntimeException)
665 OExternalLockGuard aGuard( this );
667 ::rtl::OUString aDescription;
669 if ( GetWindow() )
670 aDescription = GetWindow()->GetAccessibleDescription();
672 return aDescription;
675 ::rtl::OUString VCLXAccessibleComponent::getAccessibleName( ) throw (uno::RuntimeException)
677 OExternalLockGuard aGuard( this );
679 ::rtl::OUString aName;
680 if ( GetWindow() )
682 aName = GetWindow()->GetAccessibleName();
683 #if OSL_DEBUG_LEVEL > 1
684 aName += rtl::OUString(" (Type = ");
685 aName += rtl::OUString::valueOf(static_cast<sal_Int32>(GetWindow()->GetType()));
686 aName += rtl::OUString( ")");
687 #endif
689 return aName;
692 uno::Reference< accessibility::XAccessibleRelationSet > VCLXAccessibleComponent::getAccessibleRelationSet( ) throw (uno::RuntimeException)
694 OExternalLockGuard aGuard( this );
696 utl::AccessibleRelationSetHelper* pRelationSetHelper = new utl::AccessibleRelationSetHelper;
697 uno::Reference< accessibility::XAccessibleRelationSet > xSet = pRelationSetHelper;
698 FillAccessibleRelationSet( *pRelationSetHelper );
699 return xSet;
702 uno::Reference< accessibility::XAccessibleStateSet > VCLXAccessibleComponent::getAccessibleStateSet( ) throw (uno::RuntimeException)
704 OExternalLockGuard aGuard( this );
706 utl::AccessibleStateSetHelper* pStateSetHelper = new utl::AccessibleStateSetHelper;
707 uno::Reference< accessibility::XAccessibleStateSet > xSet = pStateSetHelper;
708 FillAccessibleStateSet( *pStateSetHelper );
709 return xSet;
712 lang::Locale VCLXAccessibleComponent::getLocale() throw (accessibility::IllegalAccessibleComponentStateException, uno::RuntimeException)
714 OExternalLockGuard aGuard( this );
716 return Application::GetSettings().GetLanguageTag().getLocale();
719 uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::getAccessibleAtPoint( const awt::Point& rPoint ) throw (uno::RuntimeException)
721 OExternalLockGuard aGuard( this );
723 uno::Reference< accessibility::XAccessible > xChild;
724 for ( sal_uInt32 i = 0, nCount = getAccessibleChildCount(); i < nCount; ++i )
726 uno::Reference< accessibility::XAccessible > xAcc = getAccessibleChild( i );
727 if ( xAcc.is() )
729 uno::Reference< accessibility::XAccessibleComponent > xComp( xAcc->getAccessibleContext(), uno::UNO_QUERY );
730 if ( xComp.is() )
732 Rectangle aRect = VCLRectangle( xComp->getBounds() );
733 Point aPos = VCLPoint( rPoint );
734 if ( aRect.IsInside( aPos ) )
736 xChild = xAcc;
737 break;
743 return xChild;
746 // accessibility::XAccessibleComponent
747 awt::Rectangle VCLXAccessibleComponent::implGetBounds() throw (uno::RuntimeException)
749 awt::Rectangle aBounds ( 0, 0, 0, 0 );
751 Window* pWindow = GetWindow();
752 if ( pWindow )
754 Rectangle aRect = pWindow->GetWindowExtentsRelative( NULL );
755 aBounds = AWTRectangle( aRect );
756 Window* pParent = pWindow->GetAccessibleParentWindow();
757 if ( pParent )
759 Rectangle aParentRect = pParent->GetWindowExtentsRelative( NULL );
760 awt::Point aParentScreenLoc = AWTPoint( aParentRect.TopLeft() );
761 aBounds.X -= aParentScreenLoc.X;
762 aBounds.Y -= aParentScreenLoc.Y;
766 uno::Reference< accessibility::XAccessible > xParent( implGetForeignControlledParent() );
767 if ( xParent.is() )
768 { // hmm, we can't rely on our VCL coordinates, as in the Accessibility Hierarchy, somebody gave
769 // us a parent which is different from our VCL parent
770 // (actually, we did not check if it's really different ...)
772 // the screen location of the foreign parent
773 uno::Reference< accessibility::XAccessibleComponent > xParentComponent( xParent->getAccessibleContext(), uno::UNO_QUERY );
774 DBG_ASSERT( xParentComponent.is(), "VCLXAccessibleComponent::implGetBounds: invalid (foreign) parent component!" );
776 awt::Point aScreenLocForeign( 0, 0 );
777 if ( xParentComponent.is() )
778 aScreenLocForeign = xParentComponent->getLocationOnScreen();
780 // the screen location of the VCL parent
781 xParent = getVclParent();
782 if ( xParent.is() )
783 xParentComponent = xParentComponent.query( xParent->getAccessibleContext() );
785 awt::Point aScreenLocVCL( 0, 0 );
786 if ( xParentComponent.is() )
787 aScreenLocVCL = xParentComponent->getLocationOnScreen();
789 // the difference between them
790 awt::Size aOffset( aScreenLocVCL.X - aScreenLocForeign.X, aScreenLocVCL.Y - aScreenLocForeign.Y );
791 // move the bounds
792 aBounds.X += aOffset.Width;
793 aBounds.Y += aOffset.Height;
796 return aBounds;
799 awt::Point VCLXAccessibleComponent::getLocationOnScreen( ) throw (uno::RuntimeException)
801 OExternalLockGuard aGuard( this );
803 awt::Point aPos;
804 if ( GetWindow() )
806 Rectangle aRect = GetWindow()->GetWindowExtentsRelative( NULL );
807 aPos.X = aRect.Left();
808 aPos.Y = aRect.Top();
811 return aPos;
814 void VCLXAccessibleComponent::grabFocus( ) throw (uno::RuntimeException)
816 OExternalLockGuard aGuard( this );
818 uno::Reference< accessibility::XAccessibleStateSet > xStates = getAccessibleStateSet();
819 if ( mxWindow.is() && xStates.is() && xStates->contains( accessibility::AccessibleStateType::FOCUSABLE ) )
820 mxWindow->setFocus();
823 sal_Int32 SAL_CALL VCLXAccessibleComponent::getForeground( ) throw (uno::RuntimeException)
825 OExternalLockGuard aGuard( this );
827 sal_Int32 nColor = 0;
828 Window* pWindow = GetWindow();
829 if ( pWindow )
831 if ( pWindow->IsControlForeground() )
832 nColor = pWindow->GetControlForeground().GetColor();
833 else
835 Font aFont;
836 if ( pWindow->IsControlFont() )
837 aFont = pWindow->GetControlFont();
838 else
839 aFont = pWindow->GetFont();
840 nColor = aFont.GetColor().GetColor();
844 return nColor;
847 sal_Int32 SAL_CALL VCLXAccessibleComponent::getBackground( ) throw (uno::RuntimeException)
849 OExternalLockGuard aGuard( this );
851 sal_Int32 nColor = 0;
852 Window* pWindow = GetWindow();
853 if ( pWindow )
855 if ( pWindow->IsControlBackground() )
856 nColor = pWindow->GetControlBackground().GetColor();
857 else
858 nColor = pWindow->GetBackground().GetColor().GetColor();
861 return nColor;
864 // XAccessibleExtendedComponent
866 uno::Reference< awt::XFont > SAL_CALL VCLXAccessibleComponent::getFont( ) throw (uno::RuntimeException)
868 OExternalLockGuard aGuard( this );
870 uno::Reference< awt::XFont > xFont;
871 Window* pWindow = GetWindow();
872 if ( pWindow )
874 uno::Reference< awt::XDevice > xDev( pWindow->GetComponentInterface(), uno::UNO_QUERY );
875 if ( xDev.is() )
877 Font aFont;
878 if ( pWindow->IsControlFont() )
879 aFont = pWindow->GetControlFont();
880 else
881 aFont = pWindow->GetFont();
882 VCLXFont* pVCLXFont = new VCLXFont;
883 pVCLXFont->Init( *xDev.get(), aFont );
884 xFont = pVCLXFont;
888 return xFont;
891 ::rtl::OUString SAL_CALL VCLXAccessibleComponent::getTitledBorderText( ) throw (uno::RuntimeException)
893 OExternalLockGuard aGuard( this );
895 ::rtl::OUString sRet;
896 if ( GetWindow() )
897 sRet = GetWindow()->GetText();
899 return sRet;
902 ::rtl::OUString SAL_CALL VCLXAccessibleComponent::getToolTipText( ) throw (uno::RuntimeException)
904 OExternalLockGuard aGuard( this );
906 ::rtl::OUString sRet;
907 if ( GetWindow() )
908 sRet = GetWindow()->GetQuickHelpText();
910 return sRet;
913 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */