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