1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 #include <cppuhelper/bootstrap.hxx>
23 #include <com/sun/star/bridge/XUnoUrlResolver.hpp>
24 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
25 #include <toolkit/awt/Vclxwindow.hxx>
26 
27 #ifndef _SV_SYSDATA_HXX
28 #if defined( WIN ) || defined( WNT ) || defined( OS2 )
29 typedef sal_Int32 HWND;
30 #endif
31 #endif
32 #include "AccEventListener.hxx"
33 #include "AccObjectManagerAgent.hxx"
34 #include "unomsaaevent.hxx"
35 
36 #include <com/sun/star/accessibility/XAccessible.hpp>
37 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
38 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
39 #include <com/sun/star/accessibility/AccessibleRole.hpp>
40 #include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
41 #include <com/sun/star/accessibility/XAccessibleComponent.hpp>
42 
43 #include <stdio.h>
44 
45 using namespace com::sun::star::uno;
46 using namespace com::sun::star::accessibility;
47 using namespace rtl;
48 using namespace cppu;
49 
AccEventListener(com::sun::star::accessibility::XAccessible * pAcc,AccObjectManagerAgent * Agent)50 AccEventListener::AccEventListener(com::sun::star::accessibility::XAccessible* pAcc,
51                                    AccObjectManagerAgent* Agent)
52         :pAccessible(pAcc),
53         pAgent(Agent),
54         m_isDisposed(false),
55         m_refcount(0)
56 {}
57 
~AccEventListener()58 AccEventListener::~AccEventListener()
59 {
60 }
61 
62 /**
63  *	Uno's event notifier when event is captured
64  *	@param AccessibleEventObject	the event object which contains information about event
65  */
notifyEvent(const::com::sun::star::accessibility::AccessibleEventObject & aEvent)66 void  AccEventListener::notifyEvent( const ::com::sun::star::accessibility::AccessibleEventObject& aEvent )
67 throw (::com::sun::star::uno::RuntimeException)
68 {
69 
70     switch (aEvent.EventId)
71     {
72     case AccessibleEventId::NAME_CHANGED:
73         handleNameChangedEvent(aEvent.NewValue);
74         break;
75     case AccessibleEventId::DESCRIPTION_CHANGED:
76         handleDescriptionChangedEvent(aEvent.NewValue);
77         break;
78     case AccessibleEventId::STATE_CHANGED:
79         handleStateChangedEvent(aEvent.OldValue, aEvent.NewValue);
80         break;
81     default:
82         break;
83     }
84 }
85 
86 /**
87  *	handle the NAME_CHANGED event
88  *	@param	name		the new name with changed.
89  */
handleNameChangedEvent(Any name)90 void AccEventListener::handleNameChangedEvent(Any name)
91 {
92     if ( pAgent->IsTopWinAcc( pAccessible ) )
93     {
94         XAccessible* pAccDoc = pAgent->GetAccDocByAccTopWin( pAccessible );
95         if ( pAccDoc )
96         {
97             pAgent->UpdateAccName(pAccDoc);
98             pAgent->NotifyAccEvent(UM_EVENT_OBJECT_NAMECHANGE, pAccDoc);
99         }
100     }
101 
102     pAgent->UpdateAccName(pAccessible, name);
103     pAgent->NotifyAccEvent(UM_EVENT_OBJECT_NAMECHANGE, pAccessible);
104 }
105 
106 /**
107  *	handle the DESCRIPTION_CHANGED event
108  *	@param	desc		the new description
109  */
handleDescriptionChangedEvent(Any desc)110 void AccEventListener::handleDescriptionChangedEvent(Any desc)
111 {
112     pAgent->UpdateDescription(pAccessible, desc);
113     pAgent->NotifyAccEvent(UM_EVENT_OBJECT_DESCRIPTIONCHANGE, pAccessible);
114 }
115 
116 /**
117  *	handle the BOUNDRECT_CHANGED event
118  */
handleBoundrectChangedEvent()119 void AccEventListener::handleBoundrectChangedEvent()
120 {
121     pAgent->UpdateLocation(pAccessible);
122     pAgent->NotifyAccEvent(UM_EVENT_BOUNDRECT_CHANGED, pAccessible);
123 }
124 
125 /**
126  *	handle the VISIBLE_DATA_CHANGED event
127  */
handleVisibleDataChangedEvent()128 void AccEventListener::handleVisibleDataChangedEvent()
129 {
130     pAgent->UpdateValue(pAccessible);
131     pAgent->NotifyAccEvent(UM_EVENT_VISIBLE_DATA_CHANGED, pAccessible);
132 }
133 
134 /**
135  *	handle the STATE_CHANGED event
136  *  @param	oldValue	the old state of the source of event
137  *  @param	newValue	the new state of the source of event
138  */
handleStateChangedEvent(Any oldValue,Any newValue)139 void AccEventListener::handleStateChangedEvent(Any oldValue, Any newValue)
140 {
141     short newV, oldV;
142     if( newValue >>= newV)
143     {
144         setComponentState(newV, true);
145     }
146     else if (oldValue >>= oldV)
147     {
148         setComponentState(oldV, false);
149     }
150 }
151 
152 /**
153  *	set the new state and fire the MSAA event
154  *	@param	state		new state id
155  *	@param	enable		true if state is set, false if state is unset
156  */
setComponentState(short state,bool enable)157 void AccEventListener::setComponentState(short state, bool enable )
158 {
159     switch (state)
160     {
161     case AccessibleStateType::FOCUSED:
162         fireStateFocusdChange(enable);
163         break;
164     default:
165         fireStatePropertyChange(state, enable);
166         break;
167     }
168 }
169 
170 /**
171  *	handle the focused event
172  *	@param enable	true if get focus, false if lose focus
173  */
fireStateFocusdChange(bool enable)174 void AccEventListener::fireStateFocusdChange(bool enable)
175 {
176     if(enable)
177     {
178         pAgent->IncreaseState( pAccessible, AccessibleStateType::FOCUSED);
179         pAgent->NotifyAccEvent(UM_EVENT_STATE_FOCUSED, pAccessible);
180     }
181     else
182     {
183         // no focus lost event in MSAA
184     }
185 }
186 
187 
188 /**
189  *	fire the MSAA state changed event
190  *	@param state	the state id
191  *	@param set		true if state is set, false if state is unset
192  */
fireStatePropertyChange(short state,bool set)193 void AccEventListener::fireStatePropertyChange(short state, bool set )
194 {
195     if( set )
196     {
197         //get new state
198     }
199     else
200     {
201         //lose old state
202     }
203 }
204 
205 /**
206  *	get the role of accessible object which is observed
207  */
getRole()208 short AccEventListener::getRole()
209 {
210     Reference<com::sun::star::accessibility::XAccessibleContext> xContext(pAccessible->getAccessibleContext(),UNO_QUERY);
211     if(xContext.is())
212     {
213         return xContext->getAccessibleRole();
214     }
215     return -1;
216 }
217 
218 /**
219  *	get the role of accessible parent object which is observed
220  */
getParentRole()221 short AccEventListener::getParentRole()
222 {
223     if(pAccessible)
224     {
225         return pAgent->GetParentRole(pAccessible);
226     }
227     return -1;
228 }
229 /**
230  *	remove the listener from accessible object
231  */
removeMeFromBroadcaster()232 void AccEventListener::removeMeFromBroadcaster()
233 {
234     try
235     {
236         vos::OGuard aGuard(aRemoveMutex);
237         if(m_isDisposed)
238             return;
239         //get accessible context
240         Reference< XAccessibleContext > pRContext;
241         XAccessibleContext* pContext =NULL;
242 
243         if( pAccessible == NULL)
244         {
245             return;
246         }
247         pRContext = pAccessible->getAccessibleContext();
248         if( !pRContext.is() )
249         {
250             return;
251         }
252 
253         //get broadcaster from accessible component
254         Reference<XAccessibleComponent> xComponent(pRContext,UNO_QUERY);
255         if(!xComponent.is())
256         {
257             return;
258         }
259         Reference<XAccessibleEventBroadcaster> broadcaster(xComponent,UNO_QUERY);
260         XAccessibleEventBroadcaster* pBroadcaster = broadcaster.get();
261         if (pBroadcaster != NULL)
262         {
263             //remove the lister from accessible object
264             pBroadcaster->removeEventListener(this);
265             m_isDisposed = true;
266             pAgent->NotifyDestroy(pAccessible);
267         }
268     }
269     catch(...)
270     {
271         return;
272     }
273 
274 }
275 
276 /**
277  *	this method is invoked before listener is disposed
278  */
disposing(const::com::sun::star::lang::EventObject & Source)279 void AccEventListener::disposing( const ::com::sun::star::lang::EventObject& Source )
280 throw (::com::sun::star::uno::RuntimeException)
281 {
282     removeMeFromBroadcaster();
283 }
284 
285 //need to investigate further
queryInterface(const::com::sun::star::uno::Type & aType)286 ::com::sun::star::uno::Any SAL_CALL AccEventListener::queryInterface( const ::com::sun::star::uno::Type& aType ) throw (::com::sun::star::uno::RuntimeException)
287 {
288     if(aType.equals(::getCppuType( (Reference< com::sun::star::accessibility::XAccessibleEventListener> const *)0 ) ))
289     {
290         Reference< com::sun::star::accessibility::XAccessibleEventListener> xEventListener( static_cast< com::sun::star::accessibility::XAccessibleEventListener* >(this));
291         return makeAny(xEventListener);
292     }
293 
294     return Any();
295 }
296 
acquire()297 void AccEventListener::acquire(  ) throw ()
298 {
299     ::osl_incrementInterlockedCount( &m_refcount );
300 }
301 
release()302 void AccEventListener::release() throw ()
303 {
304     // thread-safe decrementation of reference count
305     if (0 == ::osl_decrementInterlockedCount( &m_refcount ))
306     {
307         delete this; // shutdown this object
308     }
309 }
310