Version 5.4.3.2, tag libreoffice-5.4.3.2
[LibreOffice.git] / toolkit / source / awt / vclxaccessiblecomponent.cxx
blobba5c170faa0d92c29ae23504d8a2f31d12748f2b
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 <com/sun/star/lang/IndexOutOfBoundsException.hpp>
26 #include <cppuhelper/supportsservice.hxx>
27 #include <toolkit/awt/vclxaccessiblecomponent.hxx>
28 #include <toolkit/helper/externallock.hxx>
29 #include <toolkit/awt/vclxwindow.hxx>
30 #include <toolkit/helper/convert.hxx>
31 #include <toolkit/awt/vclxfont.hxx>
32 #include <vcl/dialog.hxx>
33 #include <vcl/vclevent.hxx>
34 #include <vcl/window.hxx>
35 #include <vcl/edit.hxx>
36 #include <vcl/settings.hxx>
37 #include <tools/debug.hxx>
38 #include <unotools/accessiblestatesethelper.hxx>
39 #include <unotools/accessiblerelationsethelper.hxx>
40 #include <vcl/svapp.hxx>
41 #include <vcl/menu.hxx>
43 using namespace ::com::sun::star;
44 using namespace ::comphelper;
46 VCLXAccessibleComponent::VCLXAccessibleComponent( VCLXWindow* pVCLXWindow )
47 : OAccessibleExtendedComponentHelper( new VCLExternalSolarLock )
48 , OAccessibleImplementationAccess( )
50 m_xVCLXWindow = pVCLXWindow;
52 m_pSolarLock = static_cast< VCLExternalSolarLock* >( getExternalLock( ) );
54 DBG_ASSERT( pVCLXWindow->GetWindow(), "VCLXAccessibleComponent - no window!" );
55 m_xEventSource = pVCLXWindow->GetWindow();
56 if ( m_xEventSource )
58 m_xEventSource->AddEventListener( LINK( this, VCLXAccessibleComponent, WindowEventListener ) );
59 m_xEventSource->AddChildEventListener( LINK( this, VCLXAccessibleComponent, WindowChildEventListener ) );
62 // announce the XAccessible of our creator to the base class
63 lateInit( pVCLXWindow );
66 VCLXWindow* VCLXAccessibleComponent::GetVCLXWindow() const
68 return m_xVCLXWindow.get();
71 void VCLXAccessibleComponent::DisconnectEvents()
73 if ( m_xEventSource )
75 m_xEventSource->RemoveEventListener( LINK( this, VCLXAccessibleComponent, WindowEventListener ) );
76 m_xEventSource->RemoveChildEventListener( LINK( this, VCLXAccessibleComponent, WindowChildEventListener ) );
77 m_xEventSource.clear();
81 VCLXAccessibleComponent::~VCLXAccessibleComponent()
83 ensureDisposed();
84 DisconnectEvents();
86 delete m_pSolarLock;
87 m_pSolarLock = nullptr;
88 // This is not completely safe. If we assume that the base class dtor calls some method which
89 // uses this lock, the we crash. However, as the base class' dtor does not have a chance to call _out_
90 // virtual methods, this is no problem as long as the base class is safe, i.e. does not use the external
91 // lock from within it's dtor. At the moment, we _know_ the base class is safe in this respect, so
92 // let's assume it keeps this way.
93 // @see OAccessibleContextHelper::OAccessibleContextHelper( IMutex* )
96 IMPLEMENT_FORWARD_XINTERFACE3( VCLXAccessibleComponent, OAccessibleExtendedComponentHelper, OAccessibleImplementationAccess, VCLXAccessibleComponent_BASE )
97 IMPLEMENT_FORWARD_XTYPEPROVIDER3( VCLXAccessibleComponent, OAccessibleExtendedComponentHelper, OAccessibleImplementationAccess, VCLXAccessibleComponent_BASE )
99 OUString VCLXAccessibleComponent::getImplementationName()
101 return OUString("com.sun.star.comp.toolkit.AccessibleWindow");
104 sal_Bool VCLXAccessibleComponent::supportsService( const OUString& rServiceName )
106 return cppu::supportsService(this, rServiceName);
109 uno::Sequence< OUString > VCLXAccessibleComponent::getSupportedServiceNames()
111 uno::Sequence< OUString > aNames { "com.sun.star.awt.AccessibleWindow" };
112 return aNames;
115 IMPL_LINK( VCLXAccessibleComponent, WindowEventListener, VclWindowEvent&, rEvent, void )
117 /* Ignore VclEventId::WindowEndPopupMode, because the UNO accessibility wrapper
118 * might have been destroyed by the previous VCLEventListener (if no AT tool
119 * is running), e.g. sub-toolbars in impress.
121 if ( m_xVCLXWindow.is() /* #122218# */ && (rEvent.GetId() != VclEventId::WindowEndPopupMode) )
123 DBG_ASSERT( rEvent.GetWindow(), "Window???" );
124 if( !rEvent.GetWindow()->IsAccessibilityEventsSuppressed() || ( rEvent.GetId() == VclEventId::ObjectDying ) )
126 ProcessWindowEvent( rEvent );
131 IMPL_LINK( VCLXAccessibleComponent, WindowChildEventListener, VclWindowEvent&, rEvent, void )
133 if ( m_xVCLXWindow.is() /* #i68079# */ )
135 DBG_ASSERT( rEvent.GetWindow(), "Window???" );
136 if( !rEvent.GetWindow()->IsAccessibilityEventsSuppressed() )
138 // #103087# to prevent an early release of the component
139 uno::Reference< accessibility::XAccessibleContext > xTmp = this;
141 ProcessWindowChildEvent( rEvent );
146 uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::GetChildAccessible( const VclWindowEvent& rVclWindowEvent )
148 // checks if the data in the window event is our direct child
149 // and returns its accessible
151 // MT: Change this later, normally a show/hide event shouldn't have the vcl::Window* in pData.
152 vcl::Window* pChildWindow = static_cast<vcl::Window *>(rVclWindowEvent.GetData());
153 if( pChildWindow && GetWindow() == pChildWindow->GetAccessibleParentWindow() )
154 return pChildWindow->GetAccessible( rVclWindowEvent.GetId() == VclEventId::WindowShow );
155 else
156 return uno::Reference< accessibility::XAccessible > ();
159 void VCLXAccessibleComponent::ProcessWindowChildEvent( const VclWindowEvent& rVclWindowEvent )
161 uno::Any aOldValue, aNewValue;
162 uno::Reference< accessibility::XAccessible > xAcc;
164 switch ( rVclWindowEvent.GetId() )
166 case VclEventId::WindowShow: // send create on show for direct accessible children
168 xAcc = GetChildAccessible( rVclWindowEvent );
169 if( xAcc.is() )
171 aNewValue <<= xAcc;
172 NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
175 break;
176 case VclEventId::WindowHide: // send destroy on hide for direct accessible children
178 xAcc = GetChildAccessible( rVclWindowEvent );
179 if( xAcc.is() )
181 aOldValue <<= xAcc;
182 NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
185 break;
186 default: break;
190 void VCLXAccessibleComponent::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
192 uno::Any aOldValue, aNewValue;
194 vcl::Window* pAccWindow = rVclWindowEvent.GetWindow();
195 assert(pAccWindow && "VCLXAccessibleComponent::ProcessWindowEvent - Window?");
197 switch ( rVclWindowEvent.GetId() )
199 case VclEventId::ObjectDying:
201 DisconnectEvents();
202 m_xVCLXWindow.clear();
204 break;
205 case VclEventId::WindowChildDestroyed:
207 vcl::Window* pWindow = static_cast<vcl::Window*>(rVclWindowEvent.GetData());
208 DBG_ASSERT( pWindow, "VclEventId::WindowChildDestroyed - Window=?" );
209 if ( pWindow->GetAccessible( false ).is() )
211 aOldValue <<= pWindow->GetAccessible( false );
212 NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
215 break;
216 case VclEventId::WindowActivate:
218 // avoid notification if a child frame is already active
219 // only one frame may be active at a given time
220 if ( !pAccWindow->HasActiveChildFrame() &&
221 ( getAccessibleRole() == accessibility::AccessibleRole::FRAME ||
222 getAccessibleRole() == accessibility::AccessibleRole::ALERT ||
223 getAccessibleRole() == accessibility::AccessibleRole::DIALOG ) ) // #i18891#
225 aNewValue <<= accessibility::AccessibleStateType::ACTIVE;
226 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
229 break;
230 case VclEventId::WindowDeactivate:
232 if ( getAccessibleRole() == accessibility::AccessibleRole::FRAME ||
233 getAccessibleRole() == accessibility::AccessibleRole::ALERT ||
234 getAccessibleRole() == accessibility::AccessibleRole::DIALOG ) // #i18891#
236 aOldValue <<= accessibility::AccessibleStateType::ACTIVE;
237 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
240 break;
241 case VclEventId::WindowGetFocus:
242 case VclEventId::ControlGetFocus:
244 if( (pAccWindow->IsCompoundControl() && rVclWindowEvent.GetId() == VclEventId::ControlGetFocus) ||
245 (!pAccWindow->IsCompoundControl() && rVclWindowEvent.GetId() == VclEventId::WindowGetFocus) )
247 // if multiple listeners were registered it is possible that the
248 // focus was changed during event processing (eg SfxTopWindow )
249 // #106082# allow ChildPathFocus only for CompoundControls, for windows the focus must be in the window itself
250 if( (pAccWindow->IsCompoundControl() && pAccWindow->HasChildPathFocus()) ||
251 (!pAccWindow->IsCompoundControl() && pAccWindow->HasFocus()) )
253 aNewValue <<= accessibility::AccessibleStateType::FOCUSED;
254 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
258 break;
259 case VclEventId::WindowLoseFocus:
260 case VclEventId::ControlLoseFocus:
262 if( (pAccWindow->IsCompoundControl() && rVclWindowEvent.GetId() == VclEventId::ControlLoseFocus) ||
263 (!pAccWindow->IsCompoundControl() && rVclWindowEvent.GetId() == VclEventId::WindowLoseFocus) )
265 aOldValue <<= accessibility::AccessibleStateType::FOCUSED;
266 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
269 break;
270 case VclEventId::WindowFrameTitleChanged:
272 OUString aOldName( *static_cast<OUString*>(rVclWindowEvent.GetData()) );
273 OUString aNewName( getAccessibleName() );
274 aOldValue <<= aOldName;
275 aNewValue <<= aNewName;
276 NotifyAccessibleEvent( accessibility::AccessibleEventId::NAME_CHANGED, aOldValue, aNewValue );
278 break;
279 case VclEventId::WindowEnabled:
281 aNewValue <<= accessibility::AccessibleStateType::ENABLED;
282 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
283 aNewValue <<= accessibility::AccessibleStateType::SENSITIVE;
284 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
286 break;
287 case VclEventId::WindowDisabled:
289 aOldValue <<= accessibility::AccessibleStateType::SENSITIVE;
290 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
292 aOldValue <<= accessibility::AccessibleStateType::ENABLED;
293 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
295 break;
296 case VclEventId::WindowMove:
297 case VclEventId::WindowResize:
299 NotifyAccessibleEvent( accessibility::AccessibleEventId::BOUNDRECT_CHANGED, aOldValue, aNewValue );
301 break;
302 case VclEventId::WindowMenubarAdded:
304 MenuBar* pMenuBar = static_cast<MenuBar*>(rVclWindowEvent.GetData());
305 if ( pMenuBar )
307 uno::Reference< accessibility::XAccessible > xChild( pMenuBar->GetAccessible() );
308 if ( xChild.is() )
310 aNewValue <<= xChild;
311 NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
315 break;
316 case VclEventId::WindowMenubarRemoved:
318 MenuBar* pMenuBar = static_cast<MenuBar*>(rVclWindowEvent.GetData());
319 if ( pMenuBar )
321 uno::Reference< accessibility::XAccessible > xChild( pMenuBar->GetAccessible() );
322 if ( xChild.is() )
324 aOldValue <<= xChild;
325 NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
329 break;
330 case VclEventId::WindowMinimize:
332 aNewValue <<= accessibility::AccessibleStateType::ICONIFIED;
333 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
335 break;
336 case VclEventId::WindowNormalize:
338 aOldValue <<= accessibility::AccessibleStateType::ICONIFIED;
339 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
341 break;
342 default:
345 break;
349 void VCLXAccessibleComponent::disposing()
351 DisconnectEvents();
353 OAccessibleExtendedComponentHelper::disposing();
355 m_xVCLXWindow.clear();
358 VclPtr<vcl::Window> VCLXAccessibleComponent::GetWindow() const
360 return GetVCLXWindow() ? GetVCLXWindow()->GetWindow()
361 : VclPtr<vcl::Window>();
364 void VCLXAccessibleComponent::FillAccessibleRelationSet( utl::AccessibleRelationSetHelper& rRelationSet )
366 VclPtr<vcl::Window> pWindow = GetWindow();
367 if ( pWindow )
369 vcl::Window *pLabeledBy = pWindow->GetAccessibleRelationLabeledBy();
370 if ( pLabeledBy && pLabeledBy != pWindow )
372 uno::Sequence< uno::Reference< uno::XInterface > > aSequence { pLabeledBy->GetAccessible() };
373 rRelationSet.AddRelation( accessibility::AccessibleRelation( accessibility::AccessibleRelationType::LABELED_BY, aSequence ) );
376 vcl::Window* pLabelFor = pWindow->GetAccessibleRelationLabelFor();
377 if ( pLabelFor && pLabelFor != pWindow )
379 uno::Sequence< uno::Reference< uno::XInterface > > aSequence { pLabelFor->GetAccessible() };
380 rRelationSet.AddRelation( accessibility::AccessibleRelation( accessibility::AccessibleRelationType::LABEL_FOR, aSequence ) );
383 vcl::Window* pMemberOf = pWindow->GetAccessibleRelationMemberOf();
384 if ( pMemberOf && pMemberOf != pWindow )
386 uno::Sequence< uno::Reference< uno::XInterface > > aSequence { pMemberOf->GetAccessible() };
387 rRelationSet.AddRelation( accessibility::AccessibleRelation( accessibility::AccessibleRelationType::MEMBER_OF, aSequence ) );
392 void VCLXAccessibleComponent::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
394 VclPtr<vcl::Window> pWindow = GetWindow();
395 if ( pWindow )
397 if ( pWindow->IsVisible() )
399 rStateSet.AddState( accessibility::AccessibleStateType::VISIBLE );
400 rStateSet.AddState( accessibility::AccessibleStateType::SHOWING );
402 else
404 rStateSet.AddState( accessibility::AccessibleStateType::INVALID );
407 if ( pWindow->IsEnabled() )
409 rStateSet.AddState( accessibility::AccessibleStateType::ENABLED );
410 rStateSet.AddState( accessibility::AccessibleStateType::SENSITIVE );
413 if ( pWindow->HasChildPathFocus() &&
414 ( getAccessibleRole() == accessibility::AccessibleRole::FRAME ||
415 getAccessibleRole() == accessibility::AccessibleRole::ALERT ||
416 getAccessibleRole() == accessibility::AccessibleRole::DIALOG ) ) // #i18891#
417 rStateSet.AddState( accessibility::AccessibleStateType::ACTIVE );
419 if ( pWindow->HasFocus() || ( pWindow->IsCompoundControl() && pWindow->HasChildPathFocus() ) )
420 rStateSet.AddState( accessibility::AccessibleStateType::FOCUSED );
422 if ( pWindow->IsWait() )
423 rStateSet.AddState( accessibility::AccessibleStateType::BUSY );
425 if ( pWindow->GetStyle() & WB_SIZEABLE )
426 rStateSet.AddState( accessibility::AccessibleStateType::RESIZABLE );
427 // 6. frame doesn't have MOVABLE state
428 // 10. for password text, where is the sensitive state?
429 if( ( getAccessibleRole() == accessibility::AccessibleRole::FRAME ||getAccessibleRole() == accessibility::AccessibleRole::DIALOG )&& pWindow->GetStyle() & WB_MOVEABLE )
430 rStateSet.AddState( accessibility::AccessibleStateType::MOVEABLE );
431 if( pWindow->IsDialog() )
433 Dialog *pDlg = static_cast< Dialog* >( pWindow.get() );
434 if( pDlg->IsInExecute() )
435 rStateSet.AddState( accessibility::AccessibleStateType::MODAL );
437 //If a combobox or list's edit child isn't read-only,EDITABLE state
438 //should be set.
439 if( pWindow && pWindow->GetType() == WindowType::COMBOBOX )
441 if( !( pWindow->GetStyle() & WB_READONLY) ||
442 !static_cast<Edit*>(pWindow.get())->IsReadOnly() )
443 rStateSet.AddState( accessibility::AccessibleStateType::EDITABLE );
446 VclPtr<vcl::Window> pChild = pWindow->GetWindow( GetWindowType::FirstChild );
448 while( pWindow && pChild )
450 VclPtr<vcl::Window> pWinTemp = pChild->GetWindow( GetWindowType::FirstChild );
451 if( pWinTemp && pWinTemp->GetType() == WindowType::EDIT )
453 if( !( pWinTemp->GetStyle() & WB_READONLY) ||
454 !static_cast<Edit*>(pWinTemp.get())->IsReadOnly() )
455 rStateSet.AddState( accessibility::AccessibleStateType::EDITABLE );
456 break;
458 if( pChild->GetType() == WindowType::EDIT )
460 if( !( pChild->GetStyle() & WB_READONLY) ||
461 !static_cast<Edit*>(pChild.get())->IsReadOnly())
462 rStateSet.AddState( accessibility::AccessibleStateType::EDITABLE );
463 break;
465 pChild = pChild->GetWindow( GetWindowType::Next );
468 else
470 rStateSet.AddState( accessibility::AccessibleStateType::DEFUNC );
475 MUST BE SET FROM DERIVED CLASSES:
477 CHECKED
478 COLLAPSED
479 EXPANDED
480 EXPANDABLE
481 EDITABLE
482 FOCUSABLE
483 HORIZONTAL
484 VERTICAL
485 ICONIFIED
486 MULTILINE
487 MULTI_SELECTABLE
488 PRESSED
489 SELECTABLE
490 SELECTED
491 SINGLE_LINE
492 TRANSIENT
498 // accessibility::XAccessibleContext
499 sal_Int32 VCLXAccessibleComponent::getAccessibleChildCount()
501 OExternalLockGuard aGuard( this );
503 sal_Int32 nChildren = 0;
504 if ( GetWindow() )
505 nChildren = GetWindow()->GetAccessibleChildWindowCount();
507 return nChildren;
510 uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::getAccessibleChild( sal_Int32 i )
512 OExternalLockGuard aGuard( this );
514 if ( i >= getAccessibleChildCount() )
515 throw lang::IndexOutOfBoundsException();
517 uno::Reference< accessibility::XAccessible > xAcc;
518 if ( GetWindow() )
520 vcl::Window* pChild = GetWindow()->GetAccessibleChildWindow( (sal_uInt16)i );
521 if ( pChild )
522 xAcc = pChild->GetAccessible();
525 return xAcc;
528 uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::getVclParent() const
530 uno::Reference< accessibility::XAccessible > xAcc;
531 if ( GetWindow() )
533 vcl::Window* pParent = GetWindow()->GetAccessibleParentWindow();
534 if ( pParent )
535 xAcc = pParent->GetAccessible();
537 return xAcc;
540 uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::getAccessibleParent( )
542 OExternalLockGuard aGuard( this );
544 uno::Reference< accessibility::XAccessible > xAcc( implGetForeignControlledParent() );
545 if ( !xAcc.is() )
546 // we do _not_ have a foreign-controlled parent -> default to our VCL parent
547 xAcc = getVclParent();
549 return xAcc;
552 sal_Int32 VCLXAccessibleComponent::getAccessibleIndexInParent( )
554 OExternalLockGuard aGuard( this );
556 sal_Int32 nIndex = -1;
558 uno::Reference< accessibility::XAccessible > xAcc( implGetForeignControlledParent() );
559 if ( xAcc.is() )
560 { // we _do_ have a foreign-controlled parent -> use the base class' implementation,
561 // which goes the UNO way
562 nIndex = OAccessibleExtendedComponentHelper::getAccessibleIndexInParent( );
564 else
566 if ( GetWindow() )
568 vcl::Window* pParent = GetWindow()->GetAccessibleParentWindow();
569 if ( pParent )
571 // Iterate over all the parent's children and search for this object.
572 // this should be compatible with the code in SVX
573 uno::Reference< accessibility::XAccessible > xParentAcc( pParent->GetAccessible() );
574 if ( xParentAcc.is() )
576 uno::Reference< accessibility::XAccessibleContext > xParentContext ( xParentAcc->getAccessibleContext() );
577 if ( xParentContext.is() )
579 sal_Int32 nChildCount = xParentContext->getAccessibleChildCount();
580 for ( sal_Int32 i=0; i<nChildCount; i++ )
582 uno::Reference< accessibility::XAccessible > xChild( xParentContext->getAccessibleChild(i) );
583 if ( xChild.is() )
585 uno::Reference< accessibility::XAccessibleContext > xChildContext = xChild->getAccessibleContext();
586 if ( xChildContext == static_cast<accessibility::XAccessibleContext*>(this) )
588 nIndex = i;
589 break;
598 return nIndex;
601 sal_Int16 VCLXAccessibleComponent::getAccessibleRole( )
603 OExternalLockGuard aGuard( this );
605 sal_Int16 nRole = 0;
607 if ( GetWindow() )
608 nRole = GetWindow()->GetAccessibleRole();
610 return nRole;
613 OUString VCLXAccessibleComponent::getAccessibleDescription( )
615 OExternalLockGuard aGuard( this );
617 OUString aDescription;
619 if ( GetWindow() )
620 aDescription = GetWindow()->GetAccessibleDescription();
622 return aDescription;
625 OUString VCLXAccessibleComponent::getAccessibleName( )
627 OExternalLockGuard aGuard( this );
629 OUString aName;
630 if ( GetWindow() )
632 aName = GetWindow()->GetAccessibleName();
633 #if OSL_DEBUG_LEVEL > 0
634 aName += " (Type = ";
635 aName += OUString::number(static_cast<sal_Int32>(GetWindow()->GetType()));
636 aName += ")";
637 #endif
639 return aName;
642 uno::Reference< accessibility::XAccessibleRelationSet > VCLXAccessibleComponent::getAccessibleRelationSet( )
644 OExternalLockGuard aGuard( this );
646 utl::AccessibleRelationSetHelper* pRelationSetHelper = new utl::AccessibleRelationSetHelper;
647 uno::Reference< accessibility::XAccessibleRelationSet > xSet = pRelationSetHelper;
648 FillAccessibleRelationSet( *pRelationSetHelper );
649 return xSet;
652 uno::Reference< accessibility::XAccessibleStateSet > VCLXAccessibleComponent::getAccessibleStateSet( )
654 OExternalLockGuard aGuard( this );
656 utl::AccessibleStateSetHelper* pStateSetHelper = new utl::AccessibleStateSetHelper;
657 uno::Reference< accessibility::XAccessibleStateSet > xSet = pStateSetHelper;
658 FillAccessibleStateSet( *pStateSetHelper );
659 return xSet;
662 lang::Locale VCLXAccessibleComponent::getLocale()
664 OExternalLockGuard aGuard( this );
666 return Application::GetSettings().GetLanguageTag().getLocale();
669 uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::getAccessibleAtPoint( const awt::Point& rPoint )
671 OExternalLockGuard aGuard( this );
673 uno::Reference< accessibility::XAccessible > xChild;
674 for ( sal_uInt32 i = 0, nCount = getAccessibleChildCount(); i < nCount; ++i )
676 uno::Reference< accessibility::XAccessible > xAcc = getAccessibleChild( i );
677 if ( xAcc.is() )
679 uno::Reference< accessibility::XAccessibleComponent > xComp( xAcc->getAccessibleContext(), uno::UNO_QUERY );
680 if ( xComp.is() )
682 tools::Rectangle aRect = VCLRectangle( xComp->getBounds() );
683 Point aPos = VCLPoint( rPoint );
684 if ( aRect.IsInside( aPos ) )
686 xChild = xAcc;
687 break;
693 return xChild;
696 // accessibility::XAccessibleComponent
697 awt::Rectangle VCLXAccessibleComponent::implGetBounds()
699 awt::Rectangle aBounds ( 0, 0, 0, 0 );
701 VclPtr<vcl::Window> pWindow = GetWindow();
702 if ( pWindow )
704 tools::Rectangle aRect = pWindow->GetWindowExtentsRelative( nullptr );
705 aBounds = AWTRectangle( aRect );
706 vcl::Window* pParent = pWindow->GetAccessibleParentWindow();
707 if ( pParent )
709 tools::Rectangle aParentRect = pParent->GetWindowExtentsRelative( nullptr );
710 awt::Point aParentScreenLoc = AWTPoint( aParentRect.TopLeft() );
711 aBounds.X -= aParentScreenLoc.X;
712 aBounds.Y -= aParentScreenLoc.Y;
716 uno::Reference< accessibility::XAccessible > xParent( implGetForeignControlledParent() );
717 if ( xParent.is() )
718 { // hmm, we can't rely on our VCL coordinates, as in the Accessibility Hierarchy, somebody gave
719 // us a parent which is different from our VCL parent
720 // (actually, we did not check if it's really different ...)
722 // the screen location of the foreign parent
723 uno::Reference< accessibility::XAccessibleComponent > xParentComponent( xParent->getAccessibleContext(), uno::UNO_QUERY );
724 DBG_ASSERT( xParentComponent.is(), "VCLXAccessibleComponent::implGetBounds: invalid (foreign) parent component!" );
726 awt::Point aScreenLocForeign( 0, 0 );
727 if ( xParentComponent.is() )
728 aScreenLocForeign = xParentComponent->getLocationOnScreen();
730 // the screen location of the VCL parent
731 xParent = getVclParent();
732 if ( xParent.is() )
733 xParentComponent.set(xParent->getAccessibleContext(), css::uno::UNO_QUERY);
735 awt::Point aScreenLocVCL( 0, 0 );
736 if ( xParentComponent.is() )
737 aScreenLocVCL = xParentComponent->getLocationOnScreen();
739 // the difference between them
740 awt::Size aOffset( aScreenLocVCL.X - aScreenLocForeign.X, aScreenLocVCL.Y - aScreenLocForeign.Y );
741 // move the bounds
742 aBounds.X += aOffset.Width;
743 aBounds.Y += aOffset.Height;
746 return aBounds;
749 awt::Point VCLXAccessibleComponent::getLocationOnScreen( )
751 OExternalLockGuard aGuard( this );
753 awt::Point aPos;
754 if ( GetWindow() )
756 tools::Rectangle aRect = GetWindow()->GetWindowExtentsRelative( nullptr );
757 aPos.X = aRect.Left();
758 aPos.Y = aRect.Top();
761 return aPos;
764 void VCLXAccessibleComponent::grabFocus( )
766 OExternalLockGuard aGuard( this );
768 uno::Reference< accessibility::XAccessibleStateSet > xStates = getAccessibleStateSet();
769 if ( m_xVCLXWindow.is() && xStates.is() && xStates->contains( accessibility::AccessibleStateType::FOCUSABLE ) )
770 m_xVCLXWindow->setFocus();
773 sal_Int32 SAL_CALL VCLXAccessibleComponent::getForeground( )
775 OExternalLockGuard aGuard( this );
777 sal_Int32 nColor = 0;
778 VclPtr<vcl::Window> pWindow = GetWindow();
779 if ( pWindow )
781 if ( pWindow->IsControlForeground() )
782 nColor = pWindow->GetControlForeground().GetColor();
783 else
785 vcl::Font aFont;
786 if ( pWindow->IsControlFont() )
787 aFont = pWindow->GetControlFont();
788 else
789 aFont = pWindow->GetFont();
790 nColor = aFont.GetColor().GetColor();
791 // COL_AUTO is not very meaningful for AT
792 if ( nColor == (sal_Int32)COL_AUTO)
793 nColor = pWindow->GetTextColor().GetColor();
797 return nColor;
800 sal_Int32 SAL_CALL VCLXAccessibleComponent::getBackground( )
802 OExternalLockGuard aGuard( this );
804 sal_Int32 nColor = 0;
805 VclPtr<vcl::Window> pWindow = GetWindow();
806 if ( pWindow )
808 if ( pWindow->IsControlBackground() )
809 nColor = pWindow->GetControlBackground().GetColor();
810 else
811 nColor = pWindow->GetBackground().GetColor().GetColor();
814 return nColor;
817 // XAccessibleExtendedComponent
819 uno::Reference< awt::XFont > SAL_CALL VCLXAccessibleComponent::getFont( )
821 OExternalLockGuard aGuard( this );
823 uno::Reference< awt::XFont > xFont;
824 VclPtr<vcl::Window> pWindow = GetWindow();
825 if ( pWindow )
827 uno::Reference< awt::XDevice > xDev( pWindow->GetComponentInterface(), uno::UNO_QUERY );
828 if ( xDev.is() )
830 vcl::Font aFont;
831 if ( pWindow->IsControlFont() )
832 aFont = pWindow->GetControlFont();
833 else
834 aFont = pWindow->GetFont();
835 VCLXFont* pVCLXFont = new VCLXFont;
836 pVCLXFont->Init( *xDev.get(), aFont );
837 xFont = pVCLXFont;
841 return xFont;
844 OUString SAL_CALL VCLXAccessibleComponent::getTitledBorderText( )
846 OExternalLockGuard aGuard( this );
848 OUString sRet;
849 if ( GetWindow() )
850 sRet = GetWindow()->GetText();
852 return sRet;
855 OUString SAL_CALL VCLXAccessibleComponent::getToolTipText( )
857 OExternalLockGuard aGuard( this );
859 OUString sRet;
860 if ( GetWindow() )
861 sRet = GetWindow()->GetQuickHelpText();
863 return sRet;
866 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */