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 void* 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 {
68
69 switch (aEvent.EventId)
70 {
71 case AccessibleEventId::NAME_CHANGED:
72 handleNameChangedEvent(aEvent.NewValue);
73 break;
74 case AccessibleEventId::DESCRIPTION_CHANGED:
75 handleDescriptionChangedEvent(aEvent.NewValue);
76 break;
77 case AccessibleEventId::STATE_CHANGED:
78 handleStateChangedEvent(aEvent.OldValue, aEvent.NewValue);
79 break;
80 default:
81 break;
82 }
83 }
84
85 /**
86 * handle the NAME_CHANGED event
87 * @param name the new name with changed.
88 */
handleNameChangedEvent(Any name)89 void AccEventListener::handleNameChangedEvent(Any name)
90 {
91 if ( pAgent->IsTopWinAcc( pAccessible ) )
92 {
93 XAccessible* pAccDoc = pAgent->GetAccDocByAccTopWin( pAccessible );
94 if ( pAccDoc )
95 {
96 pAgent->UpdateAccName(pAccDoc);
97 pAgent->NotifyAccEvent(UM_EVENT_OBJECT_NAMECHANGE, pAccDoc);
98 }
99 }
100
101 pAgent->UpdateAccName(pAccessible, name);
102 pAgent->NotifyAccEvent(UM_EVENT_OBJECT_NAMECHANGE, pAccessible);
103 }
104
105 /**
106 * handle the DESCRIPTION_CHANGED event
107 * @param desc the new description
108 */
handleDescriptionChangedEvent(Any desc)109 void AccEventListener::handleDescriptionChangedEvent(Any desc)
110 {
111 pAgent->UpdateDescription(pAccessible, desc);
112 pAgent->NotifyAccEvent(UM_EVENT_OBJECT_DESCRIPTIONCHANGE, pAccessible);
113 }
114
115 /**
116 * handle the BOUNDRECT_CHANGED event
117 */
handleBoundrectChangedEvent()118 void AccEventListener::handleBoundrectChangedEvent()
119 {
120 pAgent->UpdateLocation(pAccessible);
121 pAgent->NotifyAccEvent(UM_EVENT_BOUNDRECT_CHANGED, pAccessible);
122 }
123
124 /**
125 * handle the VISIBLE_DATA_CHANGED event
126 */
handleVisibleDataChangedEvent()127 void AccEventListener::handleVisibleDataChangedEvent()
128 {
129 pAgent->UpdateValue(pAccessible);
130 pAgent->NotifyAccEvent(UM_EVENT_VISIBLE_DATA_CHANGED, pAccessible);
131 }
132
133 /**
134 * handle the STATE_CHANGED event
135 * @param oldValue the old state of the source of event
136 * @param newValue the new state of the source of event
137 */
handleStateChangedEvent(Any oldValue,Any newValue)138 void AccEventListener::handleStateChangedEvent(Any oldValue, Any newValue)
139 {
140 short newV, oldV;
141 if( newValue >>= newV)
142 {
143 setComponentState(newV, true);
144 }
145 else if (oldValue >>= oldV)
146 {
147 setComponentState(oldV, false);
148 }
149 }
150
151 /**
152 * set the new state and fire the MSAA event
153 * @param state new state id
154 * @param enable true if state is set, false if state is unset
155 */
setComponentState(short state,bool enable)156 void AccEventListener::setComponentState(short state, bool enable )
157 {
158 switch (state)
159 {
160 case AccessibleStateType::FOCUSED:
161 fireStateFocusdChange(enable);
162 break;
163 default:
164 fireStatePropertyChange(state, enable);
165 break;
166 }
167 }
168
169 /**
170 * handle the focused event
171 * @param enable true if get focus, false if lose focus
172 */
fireStateFocusdChange(bool enable)173 void AccEventListener::fireStateFocusdChange(bool enable)
174 {
175 if(enable)
176 {
177 pAgent->IncreaseState( pAccessible, AccessibleStateType::FOCUSED);
178 pAgent->NotifyAccEvent(UM_EVENT_STATE_FOCUSED, pAccessible);
179 }
180 else
181 {
182 // no focus lost event in MSAA
183 }
184 }
185
186
187 /**
188 * fire the MSAA state changed event
189 * @param state the state id
190 * @param set true if state is set, false if state is unset
191 */
fireStatePropertyChange(short state,bool set)192 void AccEventListener::fireStatePropertyChange(short state, bool set )
193 {
194 if( set )
195 {
196 //get new state
197 }
198 else
199 {
200 //lose old state
201 }
202 }
203
204 /**
205 * get the role of accessible object which is observed
206 */
getRole()207 short AccEventListener::getRole()
208 {
209 Reference<com::sun::star::accessibility::XAccessibleContext> xContext(pAccessible->getAccessibleContext(),UNO_QUERY);
210 if(xContext.is())
211 {
212 return xContext->getAccessibleRole();
213 }
214 return -1;
215 }
216
217 /**
218 * get the role of accessible parent object which is observed
219 */
getParentRole()220 short AccEventListener::getParentRole()
221 {
222 if(pAccessible)
223 {
224 return pAgent->GetParentRole(pAccessible);
225 }
226 return -1;
227 }
228 /**
229 * remove the listener from accessible object
230 */
removeMeFromBroadcaster()231 void AccEventListener::removeMeFromBroadcaster()
232 {
233 try
234 {
235 vos::OGuard aGuard(aRemoveMutex);
236 if(m_isDisposed)
237 return;
238 //get accessible context
239 Reference< XAccessibleContext > pRContext;
240 XAccessibleContext* pContext =NULL;
241
242 if( pAccessible == NULL)
243 {
244 return;
245 }
246 pRContext = pAccessible->getAccessibleContext();
247 if( !pRContext.is() )
248 {
249 return;
250 }
251
252 //get broadcaster from accessible component
253 Reference<XAccessibleComponent> xComponent(pRContext,UNO_QUERY);
254 if(!xComponent.is())
255 {
256 return;
257 }
258 Reference<XAccessibleEventBroadcaster> broadcaster(xComponent,UNO_QUERY);
259 XAccessibleEventBroadcaster* pBroadcaster = broadcaster.get();
260 if (pBroadcaster != NULL)
261 {
262 //remove the lister from accessible object
263 pBroadcaster->removeEventListener(this);
264 m_isDisposed = true;
265 pAgent->NotifyDestroy(pAccessible);
266 }
267 }
268 catch(...)
269 {
270 return;
271 }
272
273 }
274
275 /**
276 * this method is invoked before listener is disposed
277 */
disposing(const::com::sun::star::lang::EventObject & Source)278 void AccEventListener::disposing( const ::com::sun::star::lang::EventObject& Source )
279 {
280 removeMeFromBroadcaster();
281 }
282
283 //need to investigate further
queryInterface(const::com::sun::star::uno::Type & aType)284 ::com::sun::star::uno::Any SAL_CALL AccEventListener::queryInterface( const ::com::sun::star::uno::Type& aType )
285 {
286 if(aType.equals(::getCppuType( (Reference< com::sun::star::accessibility::XAccessibleEventListener> const *)0 ) ))
287 {
288 Reference< com::sun::star::accessibility::XAccessibleEventListener> xEventListener( static_cast< com::sun::star::accessibility::XAccessibleEventListener* >(this));
289 return makeAny(xEventListener);
290 }
291
292 return Any();
293 }
294
acquire()295 void AccEventListener::acquire( ) throw ()
296 {
297 ::osl_incrementInterlockedCount( &m_refcount );
298 }
299
release()300 void AccEventListener::release() throw ()
301 {
302 // thread-safe decrementation of reference count
303 if (0 == ::osl_decrementInterlockedCount( &m_refcount ))
304 {
305 delete this; // shutdown this object
306 }
307 }
308