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 <com/sun/star/accessibility/XAccessible.hpp>
23 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
24 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
25 #include <com/sun/star/accessibility/AccessibleRole.hpp>
26 #include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
27 
28 #include "AccComponentEventListener.hxx"
29 #include "AccObjectManagerAgent.hxx"
30 #include "unomsaaevent.hxx"
31 
32 using namespace com::sun::star::uno;
33 using namespace com::sun::star::accessibility;
34 
AccComponentEventListener(com::sun::star::accessibility::XAccessible * pAcc,AccObjectManagerAgent * Agent)35 AccComponentEventListener::AccComponentEventListener(com::sun::star::accessibility::XAccessible* pAcc, AccObjectManagerAgent* Agent)
36         :AccEventListener(pAcc, Agent)
37 {
38 }
39 
~AccComponentEventListener()40 AccComponentEventListener::~AccComponentEventListener()
41 {
42 }
43 
44 /**
45  * Uno's event notifier when event is captured
46  *
47  * @param	AccessibleEventObject	the event object which contains information about event
48  */
notifyEvent(const::com::sun::star::accessibility::AccessibleEventObject & aEvent)49 void  AccComponentEventListener::notifyEvent( const ::com::sun::star::accessibility::AccessibleEventObject& aEvent )
50 throw (::com::sun::star::uno::RuntimeException)
51 {
52     switch (aEvent.EventId)
53     {
54     case AccessibleEventId::VALUE_CHANGED:
55         handleValueChangedEvent(aEvent.OldValue, aEvent.NewValue);
56         break;
57     case AccessibleEventId::ACTION_CHANGED:
58         handleActionChangedEvent();
59         break;
60     case AccessibleEventId::TEXT_CHANGED:
61         handleTextChangedEvent(aEvent.OldValue, aEvent.NewValue);
62         break;
63     case AccessibleEventId::CARET_CHANGED:
64         handleCaretChangedEvent(aEvent.OldValue, aEvent.NewValue);
65         break;
66     case AccessibleEventId::VISIBLE_DATA_CHANGED:
67         handleVisibleDataChangedEvent();
68         break;
69     case AccessibleEventId::BOUNDRECT_CHANGED:
70         handleBoundrectChangedEvent();
71         break;
72     case AccessibleEventId::SELECTION_CHANGED:
73         handleSelectionChangedEvent();
74         break;
75         //to add TEXT_SELECTION_CHANGED event
76     case AccessibleEventId::TEXT_SELECTION_CHANGED:
77         handleTextSelectionChangedEvent();
78         break;
79         //End
80     default:
81         AccEventListener::notifyEvent(aEvent);
82         break;
83     }
84 }
85 
86 /**
87  * handle the VALUE_CHANGED event
88  *
89  * @param	oldValue	the old value of the source of event
90  * @param	newValue	the new value of the source of event
91  */
handleValueChangedEvent(Any oldValue,Any newValue)92 void AccComponentEventListener::handleValueChangedEvent(Any oldValue, Any newValue)
93 {
94     pAgent->UpdateValue(pAccessible);
95     pAgent->NotifyAccEvent(UM_EVENT_OBJECT_VALUECHANGE, pAccessible);
96 }
97 
98 /**
99  * handle the NAME_CHANGED event
100  */
handleActionChangedEvent()101 void AccComponentEventListener::handleActionChangedEvent()
102 {
103     pAgent->UpdateAction(pAccessible);
104     pAgent->NotifyAccEvent(UM_EVENT_OBJECT_DEFACTIONCHANGE, pAccessible);
105 }
106 
107 /**
108  * handle the TEXT_CHANGED event
109  *
110  * @param	oldValue	the old value of the source of event
111  * @param	newValue	the new value of the source of event
112  */
handleTextChangedEvent(Any oldValue,Any newValue)113 void AccComponentEventListener::handleTextChangedEvent(Any oldValue, Any newValue)
114 {
115     pAgent->UpdateValue(pAccessible, newValue);
116     pAgent->NotifyAccEvent(UM_EVENT_OBJECT_VALUECHANGE, pAccessible);
117 }
118 
119 /**
120  * handle the CARET_CHANGED event
121  *
122  * @param	oldValue	the old value of the source of event
123  * @param	newValue	the new value of the source of event
124  */
handleCaretChangedEvent(Any oldValue,Any newValue)125 void AccComponentEventListener::handleCaretChangedEvent(Any oldValue, Any newValue)
126 {
127     pAgent->NotifyAccEvent(UM_EVENT_OBJECT_CARETCHANGE, pAccessible);
128 }
129 
130 /**
131  *	handle the VISIBLE_DATA_CHANGED event
132  */
handleVisibleDataChangedEvent()133 void AccComponentEventListener::handleVisibleDataChangedEvent()
134 {
135     AccEventListener::handleVisibleDataChangedEvent();
136 }
137 
138 /**
139  *	handle the BOUNDRECT_CHANGED event
140  */
handleBoundrectChangedEvent()141 void AccComponentEventListener::handleBoundrectChangedEvent()
142 {
143     AccEventListener::handleBoundrectChangedEvent();
144 }
145 
146 /**
147  * set the new state and fire the MSAA event
148  *
149  * @param	state	new state id
150  * @param	enable	true if state is set, false if state is unset
151  */
setComponentState(short state,bool enable)152 void AccComponentEventListener::setComponentState(short state, bool enable )
153 {
154     // only the following state can be fired state event.
155     switch (state)
156     {
157     case AccessibleStateType::CHECKED:
158     case AccessibleStateType::PRESSED:
159     case AccessibleStateType::SELECTED:
160     case AccessibleStateType::ARMED:
161     case AccessibleStateType::INDETERMINATE:
162     case AccessibleStateType::SHOWING:
163         fireStatePropertyChange(state, enable);
164         break;
165     case AccessibleStateType::VISIBLE:
166         if (getRole() == AccessibleRole::MENU_ITEM)
167         {
168             if(enable)
169             {
170                 pAgent->IncreaseState( pAccessible, AccessibleStateType::VISIBLE);
171                 pAgent->IncreaseState( pAccessible, AccessibleStateType::FOCUSABLE);
172             }
173             else
174             {
175                 pAgent->DecreaseState( pAccessible, AccessibleStateType::VISIBLE);
176                 pAgent->DecreaseState( pAccessible, AccessibleStateType::FOCUSABLE);
177             }
178         }
179         else
180         {
181             fireStatePropertyChange(state, enable);
182         }
183         break;
184         break;
185     case AccessibleStateType::FOCUSED:
186         fireStateFocusdChange(enable);
187         break;
188     case AccessibleStateType::ENABLED:
189         if(enable)
190         {
191             pAgent->UpdateState(pAccessible);
192             pAgent->DecreaseState( pAccessible, AccessibleStateType::DEFUNC);
193             // 8. label should have no FOCUSABLE state state, Firefox has READONLY state, we can also have.
194             if( getRole() != AccessibleRole::LABEL
195             && getRole() != AccessibleRole::SCROLL_BAR)
196                 pAgent->IncreaseState( pAccessible, AccessibleStateType::FOCUSABLE);
197         }
198         else
199         {
200             pAgent->UpdateState(pAccessible);
201             pAgent->IncreaseState( pAccessible, AccessibleStateType::DEFUNC);
202             pAgent->DecreaseState( pAccessible, AccessibleStateType::FOCUSABLE);
203         }
204         break;
205     case AccessibleStateType::ACTIVE:
206         // Only frames should be active
207         // no msaa state mapping
208         break;
209     default:
210         break;
211     }
212 }
213 
214 /**
215  * fire the MSAA state changed event
216  *
217  * @param	state	the state id
218  * @param	set		true if state is set, false if state is unset
219  */
fireStatePropertyChange(short state,bool set)220 void AccComponentEventListener::fireStatePropertyChange(short state, bool set)
221 {
222     if( set)
223         {
224             // new value
225             switch(state)
226             {
227             case AccessibleStateType::CHECKED:
228             case AccessibleStateType::INDETERMINATE:
229                 pAgent->IncreaseState( pAccessible, state);
230                 pAgent->UpdateAction( pAccessible );
231 
232                 if(!pAgent->IsSpecialToolboItem(pAccessible))
233                 {
234                     pAgent->NotifyAccEvent(UM_EVENT_STATE_CHECKED, pAccessible);
235                 }
236                 break;
237             case AccessibleStateType::PRESSED:
238                 pAgent->IncreaseState( pAccessible, state);
239                 pAgent->NotifyAccEvent(UM_EVENT_STATE_PRESSED, pAccessible);
240                 break;
241             case AccessibleStateType::SELECTED:
242                 pAgent->IncreaseState( pAccessible, state);
243                 break;
244             case AccessibleStateType::ARMED:
245                 pAgent->IncreaseState( pAccessible, state);
246                 pAgent->NotifyAccEvent(UM_EVENT_STATE_ARMED, pAccessible);
247                 break;
248             case AccessibleStateType::SHOWING:
249                 pAgent->DecreaseState( pAccessible, AccessibleStateType::DEFUNC);
250                 // UNO !SHOWING == MSAA OFFSCREEN
251                 pAgent->IncreaseState( pAccessible, AccessibleStateType::SHOWING );
252                 break;
253             case AccessibleStateType::VISIBLE:
254                 // UNO !VISIBLE == MSAA INVISIBLE
255                 pAgent->IncreaseState( pAccessible, AccessibleStateType::VISIBLE );
256                 break;
257             default:
258                 break;
259             }
260         }
261     else
262     {
263         // old value
264         switch(state)
265         {
266         case AccessibleStateType::CHECKED:
267         case AccessibleStateType::INDETERMINATE:
268             pAgent->DecreaseState( pAccessible, state );
269             pAgent->UpdateAction( pAccessible );
270 
271             if(!pAgent->IsSpecialToolboItem(pAccessible))
272             {
273                 pAgent->NotifyAccEvent(UM_EVENT_STATE_CHECKED, pAccessible);
274             }
275             break;
276         case AccessibleStateType::PRESSED:
277             pAgent->DecreaseState( pAccessible, state );
278             pAgent->NotifyAccEvent(UM_EVENT_STATE_PRESSED, pAccessible);
279             break;
280         case AccessibleStateType::SELECTED:
281             pAgent->DecreaseState( pAccessible, state );
282             //if the state is unset, no need to send MSAA SELECTION event
283             //pAgent->NotifyAccEvent(UM_EVENT_STATE_SELECTED, pAccessible);
284             break;
285         case AccessibleStateType::ARMED:
286             {
287                 pAgent->DecreaseState( pAccessible, state);
288                 //if the state is unset, no need to send MSAA MENU event
289                 //pAgent->NotifyAccEvent(UM_EVENT_STATE_ARMED, pAccessible);
290             }
291             break;
292         case AccessibleStateType::SHOWING:
293             pAgent->DecreaseState( pAccessible, AccessibleStateType::DEFUNC);
294             // UNO !SHOWING == MSAA OFFSCREEN
295             pAgent->DecreaseState( pAccessible, AccessibleStateType::SHOWING );
296             break;
297         case AccessibleStateType::VISIBLE:
298             // UNO !VISIBLE == MSAA INVISIBLE
299             pAgent->DecreaseState( pAccessible, AccessibleStateType::VISIBLE );
300             break;
301 
302         default:
303             break;
304         }
305     }
306 }
307 
308 /**
309  * handle the focused event
310  *
311  * @param	enable	true if get focus, false if lose focus
312  */
fireStateFocusdChange(bool enable)313 void AccComponentEventListener::fireStateFocusdChange(bool enable)
314 {
315     if(enable)
316     {
317         if(getParentRole() != AccessibleRole::COMBO_BOX )
318             pAgent->NotifyAccEvent(UM_EVENT_STATE_FOCUSED, pAccessible);
319     }
320     else
321     {
322         //if lose focus, no need to send MSAA FOCUS event
323         pAgent->DecreaseState( pAccessible, AccessibleStateType::FOCUSED);
324     }
325 }
326 
handleSelectionChangedEvent()327 void AccComponentEventListener::handleSelectionChangedEvent()
328 {
329     pAgent->NotifyAccEvent(UM_EVENT_SELECTION_CHANGED, pAccessible);
330 }
331 
332 //add TEXT_SELECTION_CHANGED event
handleTextSelectionChangedEvent()333 void AccComponentEventListener::handleTextSelectionChangedEvent()
334 {
335     pAgent->NotifyAccEvent(UM_EVENT_TEXT_SELECTION_CHANGED, pAccessible);
336 }
337