1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
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/AccessibleRelationType.hpp>
24 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
25 #include <cppuhelper/supportsservice.hxx>
26 #include <i18nlangtag/languagetag.hxx>
27 #include <toolkit/awt/vclxaccessiblecomponent.hxx>
28 #include <toolkit/awt/vclxwindow.hxx>
29 #include <toolkit/helper/convert.hxx>
30 #include <toolkit/awt/vclxfont.hxx>
31 #include <vcl/dialog.hxx>
32 #include <vcl/vclevent.hxx>
33 #include <vcl/window.hxx>
34 #include <vcl/edit.hxx>
35 #include <vcl/settings.hxx>
36 #include <tools/debug.hxx>
37 #include <unotools/accessiblestatesethelper.hxx>
38 #include <unotools/accessiblerelationsethelper.hxx>
39 #include <vcl/svapp.hxx>
40 #include <vcl/menu.hxx>
41 
42 using namespace ::com::sun::star;
43 using namespace ::comphelper;
44 
VCLXAccessibleComponent(VCLXWindow * pVCLXWindow)45 VCLXAccessibleComponent::VCLXAccessibleComponent( VCLXWindow* pVCLXWindow )
46 {
47     m_xVCLXWindow = pVCLXWindow;
48 
49     DBG_ASSERT( pVCLXWindow->GetWindow(), "VCLXAccessibleComponent - no window!" );
50     m_xEventSource = pVCLXWindow->GetWindow();
51     if ( m_xEventSource )
52     {
53         m_xEventSource->AddEventListener( LINK( this, VCLXAccessibleComponent, WindowEventListener ) );
54         m_xEventSource->AddChildEventListener( LINK( this, VCLXAccessibleComponent, WindowChildEventListener ) );
55     }
56 
57     // announce the XAccessible of our creator to the base class
58     lateInit( pVCLXWindow );
59 }
60 
GetVCLXWindow() const61 VCLXWindow* VCLXAccessibleComponent::GetVCLXWindow() const
62 {
63     return m_xVCLXWindow.get();
64 }
65 
DisconnectEvents()66 void VCLXAccessibleComponent::DisconnectEvents()
67 {
68     if ( m_xEventSource )
69     {
70         m_xEventSource->RemoveEventListener( LINK( this, VCLXAccessibleComponent, WindowEventListener ) );
71         m_xEventSource->RemoveChildEventListener( LINK( this, VCLXAccessibleComponent, WindowChildEventListener ) );
72         m_xEventSource.clear();
73     }
74 }
75 
~VCLXAccessibleComponent()76 VCLXAccessibleComponent::~VCLXAccessibleComponent()
77 {
78     ensureDisposed();
79     DisconnectEvents();
80 }
81 
IMPLEMENT_FORWARD_XINTERFACE3(VCLXAccessibleComponent,OAccessibleExtendedComponentHelper,OAccessibleImplementationAccess,VCLXAccessibleComponent_BASE)82 IMPLEMENT_FORWARD_XINTERFACE3( VCLXAccessibleComponent, OAccessibleExtendedComponentHelper, OAccessibleImplementationAccess, VCLXAccessibleComponent_BASE )
83 IMPLEMENT_FORWARD_XTYPEPROVIDER3( VCLXAccessibleComponent, OAccessibleExtendedComponentHelper, OAccessibleImplementationAccess, VCLXAccessibleComponent_BASE )
84 
85 OUString VCLXAccessibleComponent::getImplementationName()
86 {
87     return "com.sun.star.comp.toolkit.AccessibleWindow";
88 }
89 
supportsService(const OUString & rServiceName)90 sal_Bool VCLXAccessibleComponent::supportsService( const OUString& rServiceName )
91 {
92     return cppu::supportsService(this, rServiceName);
93 }
94 
getSupportedServiceNames()95 uno::Sequence< OUString > VCLXAccessibleComponent::getSupportedServiceNames()
96 {
97     uno::Sequence< OUString > aNames { "com.sun.star.awt.AccessibleWindow" };
98     return aNames;
99 }
100 
IMPL_LINK(VCLXAccessibleComponent,WindowEventListener,VclWindowEvent &,rEvent,void)101 IMPL_LINK( VCLXAccessibleComponent, WindowEventListener, VclWindowEvent&, rEvent, void )
102 {
103     /* Ignore VclEventId::WindowEndPopupMode, because the UNO accessibility wrapper
104      * might have been destroyed by the previous VCLEventListener (if no AT tool
105      * is running), e.g. sub-toolbars in impress.
106      */
107     if ( m_xVCLXWindow.is() /* #122218# */ && (rEvent.GetId() != VclEventId::WindowEndPopupMode) )
108     {
109         DBG_ASSERT( rEvent.GetWindow(), "Window???" );
110         if( !rEvent.GetWindow()->IsAccessibilityEventsSuppressed() || ( rEvent.GetId() == VclEventId::ObjectDying ) )
111         {
112             ProcessWindowEvent( rEvent );
113         }
114     }
115 }
116 
IMPL_LINK(VCLXAccessibleComponent,WindowChildEventListener,VclWindowEvent &,rEvent,void)117 IMPL_LINK( VCLXAccessibleComponent, WindowChildEventListener, VclWindowEvent&, rEvent, void )
118 {
119     if ( m_xVCLXWindow.is() /* #i68079# */ )
120     {
121         DBG_ASSERT( rEvent.GetWindow(), "Window???" );
122         if( !rEvent.GetWindow()->IsAccessibilityEventsSuppressed() )
123         {
124             // #103087# to prevent an early release of the component
125             uno::Reference< accessibility::XAccessibleContext > xTmp = this;
126 
127             ProcessWindowChildEvent( rEvent );
128         }
129     }
130 }
131 
GetChildAccessible(const VclWindowEvent & rVclWindowEvent)132 uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::GetChildAccessible( const VclWindowEvent& rVclWindowEvent )
133 {
134     // checks if the data in the window event is our direct child
135     // and returns its accessible
136 
137     // MT: Change this later, normally a show/hide event shouldn't have the vcl::Window* in pData.
138     vcl::Window* pChildWindow = static_cast<vcl::Window *>(rVclWindowEvent.GetData());
139     if( pChildWindow && GetWindow() == pChildWindow->GetAccessibleParentWindow() )
140         return pChildWindow->GetAccessible( rVclWindowEvent.GetId() == VclEventId::WindowShow );
141     else
142         return uno::Reference< accessibility::XAccessible > ();
143 }
144 
ProcessWindowChildEvent(const VclWindowEvent & rVclWindowEvent)145 void VCLXAccessibleComponent::ProcessWindowChildEvent( const VclWindowEvent& rVclWindowEvent )
146 {
147     uno::Any aOldValue, aNewValue;
148     uno::Reference< accessibility::XAccessible > xAcc;
149 
150     switch ( rVclWindowEvent.GetId() )
151     {
152         case VclEventId::WindowShow:  // send create on show for direct accessible children
153         {
154             xAcc = GetChildAccessible( rVclWindowEvent );
155             if( xAcc.is() )
156             {
157                 aNewValue <<= xAcc;
158                 NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
159             }
160         }
161         break;
162         case VclEventId::WindowHide:  // send destroy on hide for direct accessible children
163         {
164             xAcc = GetChildAccessible( rVclWindowEvent );
165             if( xAcc.is() )
166             {
167                 aOldValue <<= xAcc;
168                 NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
169             }
170         }
171         break;
172         default: break;
173     }
174 }
175 
ProcessWindowEvent(const VclWindowEvent & rVclWindowEvent)176 void VCLXAccessibleComponent::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
177 {
178     uno::Any aOldValue, aNewValue;
179 
180     vcl::Window* pAccWindow = rVclWindowEvent.GetWindow();
181     assert(pAccWindow && "VCLXAccessibleComponent::ProcessWindowEvent - Window?");
182 
183     switch ( rVclWindowEvent.GetId() )
184     {
185         case VclEventId::ObjectDying:
186         {
187             DisconnectEvents();
188             m_xVCLXWindow.clear();
189         }
190         break;
191         case VclEventId::WindowChildDestroyed:
192         {
193             vcl::Window* pWindow = static_cast<vcl::Window*>(rVclWindowEvent.GetData());
194             DBG_ASSERT( pWindow, "VclEventId::WindowChildDestroyed - Window=?" );
195             if ( pWindow->GetAccessible( false ).is() )
196             {
197                 aOldValue <<= pWindow->GetAccessible( false );
198                 NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
199             }
200         }
201         break;
202         case VclEventId::WindowActivate:
203         {
204             sal_Int16 aAccessibleRole = getAccessibleRole();
205             // avoid notification if a child frame is already active
206             // only one frame may be active at a given time
207             if ( !pAccWindow->HasActiveChildFrame() &&
208                  ( aAccessibleRole == accessibility::AccessibleRole::FRAME ||
209                    aAccessibleRole == accessibility::AccessibleRole::ALERT ||
210                    aAccessibleRole == accessibility::AccessibleRole::DIALOG ) )  // #i18891#
211             {
212                 aNewValue <<= accessibility::AccessibleStateType::ACTIVE;
213                 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
214             }
215         }
216         break;
217         case VclEventId::WindowDeactivate:
218         {
219             sal_Int16 aAccessibleRole = getAccessibleRole();
220             if ( aAccessibleRole == accessibility::AccessibleRole::FRAME ||
221                  aAccessibleRole == accessibility::AccessibleRole::ALERT ||
222                  aAccessibleRole == accessibility::AccessibleRole::DIALOG )  // #i18891#
223             {
224                 aOldValue <<= accessibility::AccessibleStateType::ACTIVE;
225                 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
226             }
227         }
228         break;
229         case VclEventId::WindowGetFocus:
230         case VclEventId::ControlGetFocus:
231         {
232             if( (pAccWindow->IsCompoundControl() && rVclWindowEvent.GetId() == VclEventId::ControlGetFocus) ||
233                 (!pAccWindow->IsCompoundControl() && rVclWindowEvent.GetId() == VclEventId::WindowGetFocus) )
234             {
235                 // if multiple listeners were registered it is possible that the
236                 // focus was changed during event processing (eg SfxTopWindow )
237                 // #106082# allow ChildPathFocus only for CompoundControls, for windows the focus must be in the window itself
238                 if( (pAccWindow->IsCompoundControl() && pAccWindow->HasChildPathFocus()) ||
239                     (!pAccWindow->IsCompoundControl() && pAccWindow->HasFocus()) )
240                 {
241                     aNewValue <<= accessibility::AccessibleStateType::FOCUSED;
242                     NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
243                 }
244             }
245         }
246         break;
247         case VclEventId::WindowLoseFocus:
248         case VclEventId::ControlLoseFocus:
249         {
250             if( (pAccWindow->IsCompoundControl() && rVclWindowEvent.GetId() == VclEventId::ControlLoseFocus) ||
251                 (!pAccWindow->IsCompoundControl() && rVclWindowEvent.GetId() == VclEventId::WindowLoseFocus) )
252             {
253                 aOldValue <<= accessibility::AccessibleStateType::FOCUSED;
254                 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
255             }
256         }
257         break;
258         case VclEventId::WindowFrameTitleChanged:
259         {
260             OUString aOldName( *static_cast<OUString*>(rVclWindowEvent.GetData()) );
261             OUString aNewName( getAccessibleName() );
262             aOldValue <<= aOldName;
263             aNewValue <<= aNewName;
264             NotifyAccessibleEvent( accessibility::AccessibleEventId::NAME_CHANGED, aOldValue, aNewValue );
265         }
266         break;
267         case VclEventId::WindowEnabled:
268         {
269             aNewValue <<= accessibility::AccessibleStateType::ENABLED;
270             NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
271             aNewValue <<= accessibility::AccessibleStateType::SENSITIVE;
272             NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
273         }
274         break;
275         case VclEventId::WindowDisabled:
276         {
277             aOldValue <<= accessibility::AccessibleStateType::SENSITIVE;
278             NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
279 
280             aOldValue <<= accessibility::AccessibleStateType::ENABLED;
281             NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
282         }
283         break;
284         case VclEventId::WindowMove:
285         case VclEventId::WindowResize:
286         {
287             NotifyAccessibleEvent( accessibility::AccessibleEventId::BOUNDRECT_CHANGED, aOldValue, aNewValue );
288         }
289         break;
290         case VclEventId::WindowMenubarAdded:
291         {
292             MenuBar* pMenuBar = static_cast<MenuBar*>(rVclWindowEvent.GetData());
293             if ( pMenuBar )
294             {
295                 uno::Reference< accessibility::XAccessible > xChild( pMenuBar->GetAccessible() );
296                 if ( xChild.is() )
297                 {
298                     aNewValue <<= xChild;
299                     NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
300                 }
301             }
302         }
303         break;
304         case VclEventId::WindowMenubarRemoved:
305         {
306             MenuBar* pMenuBar = static_cast<MenuBar*>(rVclWindowEvent.GetData());
307             if ( pMenuBar )
308             {
309                 uno::Reference< accessibility::XAccessible > xChild( pMenuBar->GetAccessible() );
310                 if ( xChild.is() )
311                 {
312                     aOldValue <<= xChild;
313                     NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue );
314                 }
315             }
316         }
317         break;
318         case VclEventId::WindowMinimize:
319         {
320             aNewValue <<= accessibility::AccessibleStateType::ICONIFIED;
321             NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
322         }
323         break;
324         case VclEventId::WindowNormalize:
325         {
326             aOldValue <<= accessibility::AccessibleStateType::ICONIFIED;
327             NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
328         }
329         break;
330         default:
331         {
332         }
333         break;
334     }
335 }
336 
disposing()337 void VCLXAccessibleComponent::disposing()
338 {
339     DisconnectEvents();
340 
341     OAccessibleExtendedComponentHelper::disposing();
342 
343     m_xVCLXWindow.clear();
344 }
345 
GetWindow() const346 VclPtr<vcl::Window> VCLXAccessibleComponent::GetWindow() const
347 {
348     return GetVCLXWindow() ? GetVCLXWindow()->GetWindow()
349                            : VclPtr<vcl::Window>();
350 }
351 
FillAccessibleRelationSet(utl::AccessibleRelationSetHelper & rRelationSet)352 void VCLXAccessibleComponent::FillAccessibleRelationSet( utl::AccessibleRelationSetHelper& rRelationSet )
353 {
354     VclPtr<vcl::Window> pWindow = GetWindow();
355     if ( pWindow )
356     {
357         vcl::Window *pLabeledBy = pWindow->GetAccessibleRelationLabeledBy();
358         if ( pLabeledBy && pLabeledBy != pWindow )
359         {
360             uno::Sequence< uno::Reference< uno::XInterface > > aSequence { pLabeledBy->GetAccessible() };
361             rRelationSet.AddRelation( accessibility::AccessibleRelation( accessibility::AccessibleRelationType::LABELED_BY, aSequence ) );
362         }
363 
364         vcl::Window* pLabelFor = pWindow->GetAccessibleRelationLabelFor();
365         if ( pLabelFor && pLabelFor != pWindow )
366         {
367             uno::Sequence< uno::Reference< uno::XInterface > > aSequence { pLabelFor->GetAccessible() };
368             rRelationSet.AddRelation( accessibility::AccessibleRelation( accessibility::AccessibleRelationType::LABEL_FOR, aSequence ) );
369         }
370 
371         vcl::Window* pMemberOf = pWindow->GetAccessibleRelationMemberOf();
372         if ( pMemberOf && pMemberOf != pWindow )
373         {
374             uno::Sequence< uno::Reference< uno::XInterface > > aSequence { pMemberOf->GetAccessible() };
375             rRelationSet.AddRelation( accessibility::AccessibleRelation( accessibility::AccessibleRelationType::MEMBER_OF, aSequence ) );
376         }
377     }
378 }
379 
FillAccessibleStateSet(utl::AccessibleStateSetHelper & rStateSet)380 void VCLXAccessibleComponent::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
381 {
382     VclPtr<vcl::Window> pWindow = GetWindow();
383     if ( pWindow )
384     {
385         if ( pWindow->IsVisible() )
386         {
387             rStateSet.AddState( accessibility::AccessibleStateType::VISIBLE );
388             rStateSet.AddState( accessibility::AccessibleStateType::SHOWING );
389         }
390         else
391         {
392             rStateSet.AddState( accessibility::AccessibleStateType::INVALID );
393         }
394 
395         if ( pWindow->IsEnabled() )
396         {
397             rStateSet.AddState( accessibility::AccessibleStateType::ENABLED );
398             rStateSet.AddState( accessibility::AccessibleStateType::SENSITIVE );
399         }
400 
401         if ( pWindow->HasChildPathFocus() &&
402              ( getAccessibleRole() == accessibility::AccessibleRole::FRAME ||
403                getAccessibleRole() == accessibility::AccessibleRole::ALERT ||
404                getAccessibleRole() == accessibility::AccessibleRole::DIALOG ) )  // #i18891#
405             rStateSet.AddState( accessibility::AccessibleStateType::ACTIVE );
406 
407         if ( pWindow->HasFocus() || ( pWindow->IsCompoundControl() && pWindow->HasChildPathFocus() ) )
408             rStateSet.AddState( accessibility::AccessibleStateType::FOCUSED );
409 
410         if ( pWindow->IsWait() )
411             rStateSet.AddState( accessibility::AccessibleStateType::BUSY );
412 
413         if ( pWindow->GetStyle() & WB_SIZEABLE )
414             rStateSet.AddState( accessibility::AccessibleStateType::RESIZABLE );
415         // 6. frame doesn't have MOVABLE state
416         // 10. for password text, where is the sensitive state?
417         if( ( getAccessibleRole() == accessibility::AccessibleRole::FRAME ||getAccessibleRole() == accessibility::AccessibleRole::DIALOG )&& pWindow->GetStyle() & WB_MOVEABLE )
418             rStateSet.AddState( accessibility::AccessibleStateType::MOVEABLE );
419         if( pWindow->IsDialog() )
420         {
421             Dialog *pDlg = static_cast< Dialog* >( pWindow.get() );
422             if( pDlg->IsInExecute() )
423                 rStateSet.AddState( accessibility::AccessibleStateType::MODAL );
424         }
425         //If a combobox or list's edit child isn't read-only,EDITABLE state
426         //should be set.
427         if( pWindow && pWindow->GetType() == WindowType::COMBOBOX )
428         {
429             if( !( pWindow->GetStyle() & WB_READONLY) ||
430                 !static_cast<Edit*>(pWindow.get())->IsReadOnly() )
431                     rStateSet.AddState( accessibility::AccessibleStateType::EDITABLE );
432         }
433 
434         VclPtr<vcl::Window> pChild = pWindow->GetWindow( GetWindowType::FirstChild );
435 
436         while( pWindow && pChild )
437         {
438             VclPtr<vcl::Window> pWinTemp = pChild->GetWindow( GetWindowType::FirstChild );
439             if( pWinTemp && pWinTemp->GetType() == WindowType::EDIT )
440             {
441                 if( !( pWinTemp->GetStyle() & WB_READONLY) ||
442                     !static_cast<Edit*>(pWinTemp.get())->IsReadOnly() )
443                     rStateSet.AddState( accessibility::AccessibleStateType::EDITABLE );
444                 break;
445             }
446             if( pChild->GetType() == WindowType::EDIT )
447             {
448                 if( !( pChild->GetStyle() & WB_READONLY) ||
449                     !static_cast<Edit*>(pChild.get())->IsReadOnly())
450                     rStateSet.AddState( accessibility::AccessibleStateType::EDITABLE );
451                 break;
452             }
453             pChild = pChild->GetWindow( GetWindowType::Next );
454         }
455     }
456     else
457     {
458         rStateSet.AddState( accessibility::AccessibleStateType::DEFUNC );
459     }
460 
461 /*
462 
463 MUST BE SET FROM DERIVED CLASSES:
464 
465 CHECKED
466 COLLAPSED
467 EXPANDED
468 EXPANDABLE
469 EDITABLE
470 FOCUSABLE
471 HORIZONTAL
472 VERTICAL
473 ICONIFIED
474 MULTILINE
475 MULTI_SELECTABLE
476 PRESSED
477 SELECTABLE
478 SELECTED
479 SINGLE_LINE
480 TRANSIENT
481 
482     */
483 }
484 
485 
486 // accessibility::XAccessibleContext
getAccessibleChildCount()487 sal_Int32 VCLXAccessibleComponent::getAccessibleChildCount()
488 {
489     OExternalLockGuard aGuard( this );
490 
491     sal_Int32 nChildren = 0;
492     if ( GetWindow() )
493         nChildren = GetWindow()->GetAccessibleChildWindowCount();
494 
495     return nChildren;
496 }
497 
getAccessibleChild(sal_Int32 i)498 uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::getAccessibleChild( sal_Int32 i )
499 {
500     OExternalLockGuard aGuard( this );
501 
502     if ( i >= getAccessibleChildCount() )
503         throw lang::IndexOutOfBoundsException();
504 
505     uno::Reference< accessibility::XAccessible > xAcc;
506     if ( GetWindow() )
507     {
508         vcl::Window* pChild = GetWindow()->GetAccessibleChildWindow( static_cast<sal_uInt16>(i) );
509         if ( pChild )
510             xAcc = pChild->GetAccessible();
511     }
512 
513     return xAcc;
514 }
515 
getVclParent() const516 uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::getVclParent() const
517 {
518     uno::Reference< accessibility::XAccessible > xAcc;
519     if ( GetWindow() )
520     {
521         vcl::Window* pParent = GetWindow()->GetAccessibleParentWindow();
522         if ( pParent )
523             xAcc = pParent->GetAccessible();
524     }
525     return xAcc;
526 }
527 
getAccessibleParent()528 uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::getAccessibleParent(  )
529 {
530     OExternalLockGuard aGuard( this );
531 
532     // we do _not_ have a foreign-controlled parent -> default to our VCL parent
533     uno::Reference< accessibility::XAccessible > xAcc = getVclParent();
534 
535     return xAcc;
536 }
537 
getAccessibleIndexInParent()538 sal_Int32 VCLXAccessibleComponent::getAccessibleIndexInParent(  )
539 {
540     OExternalLockGuard aGuard( this );
541 
542     sal_Int32 nIndex = -1;
543 
544     if ( GetWindow() )
545     {
546         vcl::Window* pParent = GetWindow()->GetAccessibleParentWindow();
547         if ( pParent )
548         {
549             //  Iterate over all the parent's children and search for this object.
550             // this should be compatible with the code in SVX
551             uno::Reference< accessibility::XAccessible > xParentAcc( pParent->GetAccessible() );
552             if ( xParentAcc.is() )
553             {
554                 uno::Reference< accessibility::XAccessibleContext > xParentContext ( xParentAcc->getAccessibleContext() );
555                 if ( xParentContext.is() )
556                 {
557                     sal_Int32 nChildCount = xParentContext->getAccessibleChildCount();
558                     for ( sal_Int32 i=0; i<nChildCount; i++ )
559                     {
560                         uno::Reference< accessibility::XAccessible > xChild( xParentContext->getAccessibleChild(i) );
561                         if ( xChild.is() )
562                         {
563                             uno::Reference< accessibility::XAccessibleContext > xChildContext = xChild->getAccessibleContext();
564                             if ( xChildContext == static_cast<accessibility::XAccessibleContext*>(this) )
565                             {
566                                 nIndex = i;
567                                 break;
568                             }
569                         }
570                     }
571                 }
572             }
573         }
574     }
575     return nIndex;
576 }
577 
getAccessibleRole()578 sal_Int16 VCLXAccessibleComponent::getAccessibleRole(  )
579 {
580     OExternalLockGuard aGuard( this );
581 
582     sal_Int16 nRole = 0;
583 
584     if ( GetWindow() )
585         nRole = GetWindow()->GetAccessibleRole();
586 
587     return nRole;
588 }
589 
getAccessibleDescription()590 OUString VCLXAccessibleComponent::getAccessibleDescription(  )
591 {
592     OExternalLockGuard aGuard( this );
593 
594     OUString aDescription;
595 
596     if ( GetWindow() )
597         aDescription = GetWindow()->GetAccessibleDescription();
598 
599     return aDescription;
600 }
601 
getAccessibleName()602 OUString VCLXAccessibleComponent::getAccessibleName(  )
603 {
604     OExternalLockGuard aGuard( this );
605 
606     OUString aName;
607     if ( GetWindow() )
608     {
609         aName = GetWindow()->GetAccessibleName();
610 #if OSL_DEBUG_LEVEL > 0
611         aName += " (Type = " + OUString::number(static_cast<sal_Int32>(GetWindow()->GetType())) + ")";
612 #endif
613     }
614     return aName;
615 }
616 
getAccessibleId()617 OUString VCLXAccessibleComponent::getAccessibleId(  )
618 {
619     OExternalLockGuard aGuard( this );
620 
621     OUString aId;
622     if ( GetWindow() )
623     {
624         const OUString &aWindowId = GetWindow()->get_id();
625         aId = aWindowId;
626     }
627     return aId;
628 }
629 
getAccessibleRelationSet()630 uno::Reference< accessibility::XAccessibleRelationSet > VCLXAccessibleComponent::getAccessibleRelationSet(  )
631 {
632     OExternalLockGuard aGuard( this );
633 
634     utl::AccessibleRelationSetHelper* pRelationSetHelper = new utl::AccessibleRelationSetHelper;
635     uno::Reference< accessibility::XAccessibleRelationSet > xSet = pRelationSetHelper;
636     FillAccessibleRelationSet( *pRelationSetHelper );
637     return xSet;
638 }
639 
getAccessibleStateSet()640 uno::Reference< accessibility::XAccessibleStateSet > VCLXAccessibleComponent::getAccessibleStateSet(  )
641 {
642     OExternalLockGuard aGuard( this );
643 
644     utl::AccessibleStateSetHelper* pStateSetHelper = new utl::AccessibleStateSetHelper;
645     uno::Reference< accessibility::XAccessibleStateSet > xSet = pStateSetHelper;
646     FillAccessibleStateSet( *pStateSetHelper );
647     return xSet;
648 }
649 
getLocale()650 lang::Locale VCLXAccessibleComponent::getLocale()
651 {
652     OExternalLockGuard aGuard( this );
653 
654     return Application::GetSettings().GetLanguageTag().getLocale();
655 }
656 
getAccessibleAtPoint(const awt::Point & rPoint)657 uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::getAccessibleAtPoint( const awt::Point& rPoint )
658 {
659     OExternalLockGuard aGuard( this );
660 
661     uno::Reference< accessibility::XAccessible > xChild;
662     for ( sal_uInt32 i = 0, nCount = getAccessibleChildCount(); i < nCount; ++i )
663     {
664         uno::Reference< accessibility::XAccessible > xAcc = getAccessibleChild( i );
665         if ( xAcc.is() )
666         {
667             uno::Reference< accessibility::XAccessibleComponent > xComp( xAcc->getAccessibleContext(), uno::UNO_QUERY );
668             if ( xComp.is() )
669             {
670                 tools::Rectangle aRect = VCLRectangle( xComp->getBounds() );
671                 Point aPos = VCLPoint( rPoint );
672                 if ( aRect.IsInside( aPos ) )
673                 {
674                     xChild = xAcc;
675                     break;
676                 }
677             }
678         }
679     }
680 
681     return xChild;
682 }
683 
684 // accessibility::XAccessibleComponent
implGetBounds()685 awt::Rectangle VCLXAccessibleComponent::implGetBounds()
686 {
687     awt::Rectangle aBounds ( 0, 0, 0, 0 );
688 
689     VclPtr<vcl::Window> pWindow = GetWindow();
690     if ( pWindow )
691     {
692         tools::Rectangle aRect = pWindow->GetWindowExtentsRelative( nullptr );
693         aBounds = AWTRectangle( aRect );
694         vcl::Window* pParent = pWindow->GetAccessibleParentWindow();
695         if ( pParent )
696         {
697             tools::Rectangle aParentRect = pParent->GetWindowExtentsRelative( nullptr );
698             awt::Point aParentScreenLoc = AWTPoint( aParentRect.TopLeft() );
699             aBounds.X -= aParentScreenLoc.X;
700             aBounds.Y -= aParentScreenLoc.Y;
701         }
702     }
703 
704     return aBounds;
705 }
706 
getLocationOnScreen()707 awt::Point VCLXAccessibleComponent::getLocationOnScreen(  )
708 {
709     OExternalLockGuard aGuard( this );
710 
711     awt::Point aPos;
712     if ( GetWindow() )
713     {
714         tools::Rectangle aRect = GetWindow()->GetWindowExtentsRelative( nullptr );
715         aPos.X = aRect.Left();
716         aPos.Y = aRect.Top();
717     }
718 
719     return aPos;
720 }
721 
grabFocus()722 void VCLXAccessibleComponent::grabFocus(  )
723 {
724     OExternalLockGuard aGuard( this );
725 
726     uno::Reference< accessibility::XAccessibleStateSet > xStates = getAccessibleStateSet();
727     if ( m_xVCLXWindow.is() && xStates.is() && xStates->contains( accessibility::AccessibleStateType::FOCUSABLE ) )
728         m_xVCLXWindow->setFocus();
729 }
730 
getForeground()731 sal_Int32 SAL_CALL VCLXAccessibleComponent::getForeground(  )
732 {
733     OExternalLockGuard aGuard( this );
734 
735     Color nColor;
736     VclPtr<vcl::Window> pWindow = GetWindow();
737     if ( pWindow )
738     {
739         if ( pWindow->IsControlForeground() )
740             nColor = pWindow->GetControlForeground();
741         else
742         {
743             vcl::Font aFont;
744             if ( pWindow->IsControlFont() )
745                 aFont = pWindow->GetControlFont();
746             else
747                 aFont = pWindow->GetFont();
748             nColor = aFont.GetColor();
749             // COL_AUTO is not very meaningful for AT
750             if ( nColor == COL_AUTO)
751                 nColor = pWindow->GetTextColor();
752         }
753     }
754 
755     return sal_Int32(nColor);
756 }
757 
getBackground()758 sal_Int32 SAL_CALL VCLXAccessibleComponent::getBackground(  )
759 {
760     OExternalLockGuard aGuard( this );
761 
762     Color nColor;
763     VclPtr<vcl::Window> pWindow = GetWindow();
764     if ( pWindow )
765     {
766         if ( pWindow->IsControlBackground() )
767             nColor = pWindow->GetControlBackground();
768         else
769             nColor = pWindow->GetBackground().GetColor();
770     }
771 
772     return sal_Int32(nColor);
773 }
774 
775 // XAccessibleExtendedComponent
776 
getFont()777 uno::Reference< awt::XFont > SAL_CALL VCLXAccessibleComponent::getFont(  )
778 {
779     OExternalLockGuard aGuard( this );
780 
781     uno::Reference< awt::XFont > xFont;
782     VclPtr<vcl::Window> pWindow = GetWindow();
783     if ( pWindow )
784     {
785         uno::Reference< awt::XDevice > xDev( pWindow->GetComponentInterface(), uno::UNO_QUERY );
786         if ( xDev.is() )
787         {
788             vcl::Font aFont;
789             if ( pWindow->IsControlFont() )
790                 aFont = pWindow->GetControlFont();
791             else
792                 aFont = pWindow->GetFont();
793             VCLXFont* pVCLXFont = new VCLXFont;
794             pVCLXFont->Init( *xDev, aFont );
795             xFont = pVCLXFont;
796         }
797     }
798 
799     return xFont;
800 }
801 
getTitledBorderText()802 OUString SAL_CALL VCLXAccessibleComponent::getTitledBorderText(  )
803 {
804     OExternalLockGuard aGuard( this );
805 
806     OUString sRet;
807     if ( GetWindow() )
808         sRet = GetWindow()->GetText();
809 
810     return sRet;
811 }
812 
getToolTipText()813 OUString SAL_CALL VCLXAccessibleComponent::getToolTipText(  )
814 {
815     OExternalLockGuard aGuard( this );
816 
817     OUString sRet;
818     if ( GetWindow() )
819         sRet = GetWindow()->GetQuickHelpText();
820 
821     return sRet;
822 }
823 
824 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
825