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>
26 #include <sal/log.hxx>
28 using namespace ::com::sun::star::accessibility
;
29 using namespace ::com::sun::star::lang
;
30 using namespace ::com::sun::star::uno
;
32 DocumentFocusListener::DocumentFocusListener(AquaA11yFocusTracker
& rTracker
) :
33 m_aFocusTracker(rTracker
)
38 DocumentFocusListener::disposing( const EventObject
& aEvent
)
40 // Unref the object here, but do not remove as listener since the object
41 // might no longer be in a state that safely allows this.
42 if( aEvent
.Source
.is() )
43 m_aRefList
.erase(aEvent
.Source
);
47 DocumentFocusListener::notifyEvent( const AccessibleEventObject
& aEvent
)
50 switch( aEvent
.EventId
)
52 case AccessibleEventId::STATE_CHANGED
:
54 sal_Int16 nState
= AccessibleStateType::INVALID
;
55 aEvent
.NewValue
>>= nState
;
57 if( AccessibleStateType::FOCUSED
== nState
)
58 m_aFocusTracker
.setFocusedObject( getAccessible(aEvent
) );
62 case AccessibleEventId::CHILD
:
64 Reference
< XAccessible
> xChild
;
65 if( (aEvent
.OldValue
>>= xChild
) && xChild
.is() )
66 detachRecursive(xChild
);
68 if( (aEvent
.NewValue
>>= xChild
) && xChild
.is() )
69 attachRecursive(xChild
);
73 case AccessibleEventId::INVALIDATE_ALL_CHILDREN
:
75 Reference
< XAccessible
> xAccessible( getAccessible(aEvent
) );
76 detachRecursive(xAccessible
);
77 attachRecursive(xAccessible
);
78 SAL_INFO("vcl", "Invalidate all children called" );
86 catch (const IndexOutOfBoundsException
&)
88 SAL_WARN("vcl", "Focused object has invalid index in parent");
92 Reference
< XAccessible
> DocumentFocusListener::getAccessible(const EventObject
& aEvent
)
94 Reference
< XAccessible
> xAccessible(aEvent
.Source
, UNO_QUERY
);
96 if( xAccessible
.is() )
99 Reference
< XAccessibleContext
> xContext(aEvent
.Source
, UNO_QUERY
);
103 Reference
< XAccessible
> xParent( xContext
->getAccessibleParent() );
106 Reference
< XAccessibleContext
> xParentContext( xParent
->getAccessibleContext() );
107 if( xParentContext
.is() )
109 return xParentContext
->getAccessibleChild( xContext
->getAccessibleIndexInParent() );
114 return Reference
< XAccessible
>();
117 void DocumentFocusListener::attachRecursive(const Reference
< XAccessible
>& xAccessible
)
119 Reference
< XAccessibleContext
> xContext
= xAccessible
->getAccessibleContext();
122 attachRecursive(xAccessible
, xContext
);
125 void DocumentFocusListener::attachRecursive(
126 const Reference
< XAccessible
>& xAccessible
,
127 const Reference
< XAccessibleContext
>& xContext
132 Reference
< XAccessibleStateSet
> xStateSet
= xContext
->getAccessibleStateSet();
135 attachRecursive(xAccessible
, xContext
, xStateSet
);
139 void DocumentFocusListener::attachRecursive(
140 const Reference
< XAccessible
>& xAccessible
,
141 const Reference
< XAccessibleContext
>& xContext
,
142 const Reference
< XAccessibleStateSet
>& xStateSet
145 if( xStateSet
->contains(AccessibleStateType::FOCUSED
) )
146 m_aFocusTracker
.setFocusedObject( xAccessible
);
148 Reference
< XAccessibleEventBroadcaster
> xBroadcaster(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(xContext
, UNO_QUERY
);
196 if( xBroadcaster
.is() && 0 < m_aRefList
.erase(xBroadcaster
) )
198 xBroadcaster
->removeAccessibleEventListener(static_cast< XAccessibleEventListener
*>(this));
200 if( ! xStateSet
->contains(AccessibleStateType::MANAGES_DESCENDANTS
) )
202 sal_Int32 n
, nmax
= xContext
->getAccessibleChildCount();
203 for( n
= 0; n
< nmax
; n
++ )
205 Reference
< XAccessible
> xChild( xContext
->getAccessibleChild( n
) );
208 detachRecursive(xChild
);
214 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */