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>
26 #include <osl/diagnose.h>
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
)
39 throw (RuntimeException
, std::exception
)
41 // Unref the object here, but do not remove as listener since the object
42 // might no longer be in a state that safely allows this.
43 if( aEvent
.Source
.is() )
44 m_aRefList
.erase(aEvent
.Source
);
48 DocumentFocusListener::notifyEvent( const AccessibleEventObject
& aEvent
)
49 throw( RuntimeException
, std::exception
)
52 switch( aEvent
.EventId
)
54 case AccessibleEventId::STATE_CHANGED
:
56 sal_Int16 nState
= AccessibleStateType::INVALID
;
57 aEvent
.NewValue
>>= nState
;
59 if( AccessibleStateType::FOCUSED
== nState
)
60 m_aFocusTracker
.setFocusedObject( getAccessible(aEvent
) );
64 case AccessibleEventId::CHILD
:
66 Reference
< XAccessible
> xChild
;
67 if( (aEvent
.OldValue
>>= xChild
) && xChild
.is() )
68 detachRecursive(xChild
);
70 if( (aEvent
.NewValue
>>= xChild
) && xChild
.is() )
71 attachRecursive(xChild
);
75 case AccessibleEventId::INVALIDATE_ALL_CHILDREN
:
77 Reference
< XAccessible
> xAccessible( getAccessible(aEvent
) );
78 detachRecursive(xAccessible
);
79 attachRecursive(xAccessible
);
81 OSL_TRACE( "Invalidate all children called\n" );
88 catch (const IndexOutOfBoundsException
&)
90 OSL_TRACE("Focused object has invalid index in parent");
94 Reference
< XAccessible
> DocumentFocusListener::getAccessible(const EventObject
& aEvent
)
95 throw (IndexOutOfBoundsException
, RuntimeException
)
97 Reference
< XAccessible
> xAccessible(aEvent
.Source
, UNO_QUERY
);
99 if( xAccessible
.is() )
102 Reference
< XAccessibleContext
> xContext(aEvent
.Source
, UNO_QUERY
);
106 Reference
< XAccessible
> xParent( xContext
->getAccessibleParent() );
109 Reference
< XAccessibleContext
> xParentContext( xParent
->getAccessibleContext() );
110 if( xParentContext
.is() )
112 return xParentContext
->getAccessibleChild( xContext
->getAccessibleIndexInParent() );
117 return Reference
< XAccessible
>();
120 void DocumentFocusListener::attachRecursive(const Reference
< XAccessible
>& xAccessible
)
121 throw (IndexOutOfBoundsException
, RuntimeException
)
123 Reference
< XAccessibleContext
> xContext
= xAccessible
->getAccessibleContext();
126 attachRecursive(xAccessible
, xContext
);
129 void DocumentFocusListener::attachRecursive(
130 const Reference
< XAccessible
>& xAccessible
,
131 const Reference
< XAccessibleContext
>& xContext
132 ) throw (IndexOutOfBoundsException
, RuntimeException
)
136 Reference
< XAccessibleStateSet
> xStateSet
= xContext
->getAccessibleStateSet();
139 attachRecursive(xAccessible
, xContext
, xStateSet
);
143 void DocumentFocusListener::attachRecursive(
144 const Reference
< XAccessible
>& xAccessible
,
145 const Reference
< XAccessibleContext
>& xContext
,
146 const Reference
< XAccessibleStateSet
>& xStateSet
147 ) throw (IndexOutOfBoundsException
,RuntimeException
)
149 if( xStateSet
->contains(AccessibleStateType::FOCUSED
) )
150 m_aFocusTracker
.setFocusedObject( xAccessible
);
152 Reference
< XAccessibleEventBroadcaster
> xBroadcaster
=
153 Reference
< XAccessibleEventBroadcaster
>(xContext
, UNO_QUERY
);
155 // If not already done, add the broadcaster to the list and attach as listener.
156 if( xBroadcaster
.is() && m_aRefList
.insert(xBroadcaster
).second
)
158 xBroadcaster
->addAccessibleEventListener(static_cast< XAccessibleEventListener
*>(this));
160 if( ! xStateSet
->contains(AccessibleStateType::MANAGES_DESCENDANTS
) )
162 sal_Int32 n
, nmax
= xContext
->getAccessibleChildCount();
163 for( n
= 0; n
< nmax
; n
++ )
165 Reference
< XAccessible
> xChild( xContext
->getAccessibleChild( n
) );
168 attachRecursive(xChild
);
174 void DocumentFocusListener::detachRecursive(const Reference
< XAccessible
>& xAccessible
)
175 throw (IndexOutOfBoundsException
, RuntimeException
)
177 Reference
< XAccessibleContext
> xContext
= xAccessible
->getAccessibleContext();
180 detachRecursive(xAccessible
, xContext
);
183 void DocumentFocusListener::detachRecursive(
184 const Reference
< XAccessible
>& xAccessible
,
185 const Reference
< XAccessibleContext
>& xContext
186 ) throw (IndexOutOfBoundsException
, RuntimeException
)
188 Reference
< XAccessibleStateSet
> xStateSet
= xContext
->getAccessibleStateSet();
191 detachRecursive(xAccessible
, xContext
, xStateSet
);
194 void DocumentFocusListener::detachRecursive(
195 const Reference
< XAccessible
>&,
196 const Reference
< XAccessibleContext
>& xContext
,
197 const Reference
< XAccessibleStateSet
>& xStateSet
198 ) throw (IndexOutOfBoundsException
, RuntimeException
)
200 Reference
< XAccessibleEventBroadcaster
> xBroadcaster
=
201 Reference
< XAccessibleEventBroadcaster
>(xContext
, UNO_QUERY
);
203 if( xBroadcaster
.is() && 0 < m_aRefList
.erase(xBroadcaster
) )
205 xBroadcaster
->removeAccessibleEventListener(static_cast< XAccessibleEventListener
*>(this));
207 if( ! xStateSet
->contains(AccessibleStateType::MANAGES_DESCENDANTS
) )
209 sal_Int32 n
, nmax
= xContext
->getAccessibleChildCount();
210 for( n
= 0; n
< nmax
; n
++ )
212 Reference
< XAccessible
> xChild( xContext
->getAccessibleChild( n
) );
215 detachRecursive(xChild
);
221 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */