1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 "documentfocuslistener.hxx"
22 #include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
23 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
24 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
25 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
27 using namespace ::com::sun::star::accessibility
;
28 using namespace ::com::sun::star::lang
;
29 using namespace ::com::sun::star::uno
;
31 DocumentFocusListener::DocumentFocusListener(AquaA11yFocusTracker
& rTracker
) :
32 m_aFocusTracker(rTracker
)
37 DocumentFocusListener::disposing( const EventObject
& aEvent
)
39 // Unref the object here, but do not remove as listener since the object
40 // might no longer be in a state that safely allows this.
41 if( aEvent
.Source
.is() )
42 m_aRefList
.erase(aEvent
.Source
);
46 DocumentFocusListener::notifyEvent( const AccessibleEventObject
& aEvent
)
49 switch( aEvent
.EventId
)
51 case AccessibleEventId::STATE_CHANGED
:
53 sal_Int16 nState
= AccessibleStateType::INVALID
;
54 aEvent
.NewValue
>>= nState
;
56 if( AccessibleStateType::FOCUSED
== nState
)
57 m_aFocusTracker
.setFocusedObject( getAccessible(aEvent
) );
61 case AccessibleEventId::CHILD
:
63 Reference
< XAccessible
> xChild
;
64 if( (aEvent
.OldValue
>>= xChild
) && xChild
.is() )
65 detachRecursive(xChild
);
67 if( (aEvent
.NewValue
>>= xChild
) && xChild
.is() )
68 attachRecursive(xChild
);
72 case AccessibleEventId::INVALIDATE_ALL_CHILDREN
:
74 Reference
< XAccessible
> xAccessible( getAccessible(aEvent
) );
75 detachRecursive(xAccessible
);
76 attachRecursive(xAccessible
);
77 SAL_INFO("vcl", "Invalidate all children called" );
85 catch (const IndexOutOfBoundsException
&)
87 SAL_WARN("vcl", "Focused object has invalid index in parent");
91 Reference
< XAccessible
> DocumentFocusListener::getAccessible(const EventObject
& aEvent
)
93 Reference
< XAccessible
> xAccessible(aEvent
.Source
, UNO_QUERY
);
95 if( xAccessible
.is() )
98 Reference
< XAccessibleContext
> xContext(aEvent
.Source
, UNO_QUERY
);
102 Reference
< XAccessible
> xParent( xContext
->getAccessibleParent() );
105 Reference
< XAccessibleContext
> xParentContext( xParent
->getAccessibleContext() );
106 if( xParentContext
.is() )
108 return xParentContext
->getAccessibleChild( xContext
->getAccessibleIndexInParent() );
113 return Reference
< XAccessible
>();
116 void DocumentFocusListener::attachRecursive(const Reference
< XAccessible
>& xAccessible
)
118 Reference
< XAccessibleContext
> xContext
= xAccessible
->getAccessibleContext();
121 attachRecursive(xAccessible
, xContext
);
124 void DocumentFocusListener::attachRecursive(
125 const Reference
< XAccessible
>& xAccessible
,
126 const Reference
< XAccessibleContext
>& xContext
131 Reference
< XAccessibleStateSet
> xStateSet
= xContext
->getAccessibleStateSet();
134 attachRecursive(xAccessible
, xContext
, xStateSet
);
138 void DocumentFocusListener::attachRecursive(
139 const Reference
< XAccessible
>& xAccessible
,
140 const Reference
< XAccessibleContext
>& xContext
,
141 const Reference
< XAccessibleStateSet
>& xStateSet
144 if( xStateSet
->contains(AccessibleStateType::FOCUSED
) )
145 m_aFocusTracker
.setFocusedObject( xAccessible
);
147 Reference
< XAccessibleEventBroadcaster
> xBroadcaster
=
148 Reference
< XAccessibleEventBroadcaster
>(xContext
, UNO_QUERY
);
150 // If not already done, add the broadcaster to the list and attach as listener.
151 if( xBroadcaster
.is() && m_aRefList
.insert(xBroadcaster
).second
)
153 xBroadcaster
->addAccessibleEventListener(static_cast< XAccessibleEventListener
*>(this));
155 if( ! xStateSet
->contains(AccessibleStateType::MANAGES_DESCENDANTS
) )
157 sal_Int32 n
, nmax
= xContext
->getAccessibleChildCount();
158 for( n
= 0; n
< nmax
; n
++ )
160 Reference
< XAccessible
> xChild( xContext
->getAccessibleChild( n
) );
163 attachRecursive(xChild
);
169 void DocumentFocusListener::detachRecursive(const Reference
< XAccessible
>& xAccessible
)
171 Reference
< XAccessibleContext
> xContext
= xAccessible
->getAccessibleContext();
174 detachRecursive(xAccessible
, xContext
);
177 void DocumentFocusListener::detachRecursive(
178 const Reference
< XAccessible
>& xAccessible
,
179 const Reference
< XAccessibleContext
>& xContext
182 Reference
< XAccessibleStateSet
> xStateSet
= xContext
->getAccessibleStateSet();
185 detachRecursive(xAccessible
, xContext
, xStateSet
);
188 void DocumentFocusListener::detachRecursive(
189 const Reference
< XAccessible
>&,
190 const Reference
< XAccessibleContext
>& xContext
,
191 const Reference
< XAccessibleStateSet
>& xStateSet
194 Reference
< XAccessibleEventBroadcaster
> xBroadcaster
=
195 Reference
< XAccessibleEventBroadcaster
>(xContext
, UNO_QUERY
);
197 if( xBroadcaster
.is() && 0 < m_aRefList
.erase(xBroadcaster
) )
199 xBroadcaster
->removeAccessibleEventListener(static_cast< XAccessibleEventListener
*>(this));
201 if( ! xStateSet
->contains(AccessibleStateType::MANAGES_DESCENDANTS
) )
203 sal_Int32 n
, nmax
= xContext
->getAccessibleChildCount();
204 for( n
= 0; n
< nmax
; n
++ )
206 Reference
< XAccessible
> xChild( xContext
->getAccessibleChild( n
) );
209 detachRecursive(xChild
);
215 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */