1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <com/sun/star/uno/Sequence.h>
21 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
22 #include <com/sun/star/accessibility/AccessibleRole.hpp>
23 #include <com/sun/star/accessibility/XAccessibleValue.hpp>
24 #include <com/sun/star/accessibility/XAccessibleComponent.hpp>
25 #include <com/sun/star/accessibility/XAccessibleText.hpp>
26 
27 #include <o3tl/char16_t2wchar_t.hxx>
28 
29 #include <stdlib.h>
30 #include <memory.h>
31 #include <stdio.h>
32 #include <algorithm>
33 #include <assert.h>
34 
35 #include <AccObject.hxx>
36 #include <AccEventListener.hxx>
37 
38 #if defined __clang__
39 #pragma clang diagnostic push
40 #pragma clang diagnostic ignored "-Wextra-tokens"
41     // "#endif !_MIDL_USE_GUIDDEF_" in midl-generated code
42 #endif
43 #include <UAccCOM_i.c>
44 #if defined __clang__
45 #pragma clang diagnostic pop
46 #endif
47 
48 using namespace std;
49 using namespace com::sun::star::uno;
50 using namespace com::sun::star::accessibility;
51 using namespace com::sun::star::accessibility::AccessibleRole;
52 using namespace com::sun::star::accessibility::AccessibleStateType;
53 
54 //Role mapping table,left side is UNO role, right side is MSAA role
55 const short ROLE_TABLE[][2] =
56     {
57         {UNKNOWN,                  IA2_ROLE_UNKNOWN},
58         {ALERT ,                   ROLE_SYSTEM_DIALOG},
59         {COLUMN_HEADER ,           ROLE_SYSTEM_COLUMNHEADER},
60         //{CANVAS ,                  ROLE_SYSTEM_CLIENT},
61         {CANVAS ,                  IA2_ROLE_CANVAS},
62         {CHECK_BOX ,               ROLE_SYSTEM_CHECKBUTTON},
63         {CHECK_MENU_ITEM ,         IA2_ROLE_CHECK_MENU_ITEM},
64         {COLOR_CHOOSER,            IA2_ROLE_COLOR_CHOOSER},
65         {COMBO_BOX ,               ROLE_SYSTEM_COMBOBOX},
66         {DATE_EDITOR ,             IA2_ROLE_DATE_EDITOR},
67         {DESKTOP_ICON ,            IA2_ROLE_DESKTOP_ICON},
68         {DESKTOP_PANE,             IA2_ROLE_DESKTOP_PANE},
69         {DIRECTORY_PANE,           IA2_ROLE_DIRECTORY_PANE},
70         {DIALOG,                   ROLE_SYSTEM_DIALOG},
71         {DOCUMENT,                 ROLE_SYSTEM_DOCUMENT},
72         {EMBEDDED_OBJECT ,         IA2_ROLE_EMBEDDED_OBJECT },
73         {END_NOTE ,                IA2_ROLE_ENDNOTE },
74         {FILE_CHOOSER ,            IA2_ROLE_FILE_CHOOSER },
75         {FILLER,                   ROLE_SYSTEM_WHITESPACE},
76         {FONT_CHOOSER,             IA2_ROLE_FONT_CHOOSER},
77         {FOOTER,                   IA2_ROLE_FOOTER},
78         {FOOTNOTE,                 IA2_ROLE_FOOTNOTE},
79         //{FRAME,                      IA2_ROLE_FRAME},
80         {FRAME,                    ROLE_SYSTEM_DIALOG},
81         {GLASS_PANE ,              IA2_ROLE_GLASS_PANE},
82         {GRAPHIC ,                 ROLE_SYSTEM_GRAPHIC},
83         {GROUP_BOX,                ROLE_SYSTEM_GROUPING},
84         {HEADER ,                  IA2_ROLE_HEADER},
85         {HEADING ,                 IA2_ROLE_HEADING},
86         {HYPER_LINK ,              ROLE_SYSTEM_TEXT},
87         {ICON ,                    IA2_ROLE_ICON},
88         {INTERNAL_FRAME,           IA2_ROLE_INTERNAL_FRAME},
89         {LABEL,                    ROLE_SYSTEM_STATICTEXT},
90         {LAYERED_PANE ,            IA2_ROLE_LAYERED_PANE},
91         {LIST ,                    ROLE_SYSTEM_LIST},
92         {LIST_ITEM ,               ROLE_SYSTEM_LISTITEM},
93         //{MENU ,                    ROLE_SYSTEM_MENUPOPUP},
94         {MENU,                ROLE_SYSTEM_MENUITEM},
95         {MENU_BAR,                 ROLE_SYSTEM_MENUBAR},
96         {MENU_ITEM,                ROLE_SYSTEM_MENUITEM},
97         {OPTION_PANE ,             IA2_ROLE_OPTION_PANE},
98         {PAGE_TAB,                 ROLE_SYSTEM_PAGETAB},
99         {PAGE_TAB_LIST,            ROLE_SYSTEM_PAGETABLIST},
100         {PANEL,                    IA2_ROLE_OPTION_PANE},
101         {PARAGRAPH,                IA2_ROLE_PARAGRAPH},
102         {PASSWORD_TEXT,            ROLE_SYSTEM_TEXT},
103         {POPUP_MENU,               ROLE_SYSTEM_MENUPOPUP},
104         {PUSH_BUTTON,              ROLE_SYSTEM_PUSHBUTTON},
105         {PROGRESS_BAR,             ROLE_SYSTEM_PROGRESSBAR},
106         {RADIO_BUTTON,             ROLE_SYSTEM_RADIOBUTTON},
107         {RADIO_MENU_ITEM,          IA2_ROLE_RADIO_MENU_ITEM},
108         {ROW_HEADER ,              ROLE_SYSTEM_ROWHEADER},
109         {ROOT_PANE,                IA2_ROLE_ROOT_PANE},
110         {SCROLL_BAR ,              ROLE_SYSTEM_SCROLLBAR},
111         {SCROLL_PANE ,             IA2_ROLE_SCROLL_PANE},
112         {SHAPE,                    IA2_ROLE_SHAPE},
113         {SEPARATOR ,               ROLE_SYSTEM_SEPARATOR},
114         {SLIDER ,                  ROLE_SYSTEM_SLIDER},
115         {SPIN_BOX ,                ROLE_SYSTEM_SPINBUTTON},
116         {SPLIT_PANE,               IA2_ROLE_SPLIT_PANE},
117         {STATUS_BAR,               ROLE_SYSTEM_STATUSBAR},
118         {TABLE,                    ROLE_SYSTEM_TABLE},
119         {TABLE_CELL ,              ROLE_SYSTEM_CELL},
120         {TEXT,                     ROLE_SYSTEM_TEXT},
121         {TEXT_FRAME ,              IA2_ROLE_TEXT_FRAME},
122         //for change toggle button to push button for jaws
123         {TOGGLE_BUTTON,            ROLE_SYSTEM_PUSHBUTTON},
124 
125         {TOOL_BAR,                 ROLE_SYSTEM_TOOLBAR},
126         {TOOL_TIP,                 ROLE_SYSTEM_TOOLTIP},
127         {TREE ,                    ROLE_SYSTEM_OUTLINE},
128         {VIEW_PORT ,               IA2_ROLE_VIEW_PORT},
129         {WINDOW,                   ROLE_SYSTEM_WINDOW},
130         {BUTTON_DROPDOWN,  ROLE_SYSTEM_BUTTONDROPDOWN},
131         {BUTTON_MENU,             ROLE_SYSTEM_BUTTONMENU},
132         {CAPTION,                   IA2_ROLE_CAPTION},
133         {CHART,                     IA2_ROLE_SHAPE},
134         {EDIT_BAR,                  IA2_ROLE_EDITBAR},
135         {FORM,                      IA2_ROLE_FORM},
136         {IMAGE_MAP ,                IA2_ROLE_IMAGE_MAP},
137         {NOTE,                      IA2_ROLE_NOTE},
138         {PAGE,                      IA2_ROLE_PAGE},
139         {RULER ,                    IA2_ROLE_RULER},
140         {SECTION,                   IA2_ROLE_SECTION},
141         {TREE_ITEM ,                ROLE_SYSTEM_OUTLINEITEM},
142         {TREE_TABLE,                ROLE_SYSTEM_OUTLINE},
143         {COMMENT,                   IA2_ROLE_TEXT_FRAME },
144         {COMMENT_END,               IA2_ROLE_TEXT_FRAME },
145         {DOCUMENT_PRESENTATION,     ROLE_SYSTEM_DOCUMENT },
146         {DOCUMENT_SPREADSHEET,      ROLE_SYSTEM_DOCUMENT },
147         {DOCUMENT_TEXT,             ROLE_SYSTEM_DOCUMENT },
148         {STATIC,                    IA2_ROLE_TEXT_FRAME }
149     };
150 
151 
152 /**
153    * Constructor.
154    * @param pXAcc Uno XAccessible interface of control.
155    * @param Agent The agent kept in all listeners,it's the sole interface by which
156    *              listener communicate with windows manager.
157    * @param listener listener that registers in UNO system.
158    * @return.
159    */
AccObject(XAccessible * pAcc,AccObjectManagerAgent * pAgent,AccEventListener * pListener)160 AccObject::AccObject(XAccessible* pAcc, AccObjectManagerAgent* pAgent,
161                      AccEventListener* pListener) :
162         m_resID     (NULL),
163         m_pParantID (nullptr),
164         m_bShouldDestroy(false),
165         m_pIMAcc    (nullptr),
166         m_pParentObj(nullptr),
167         m_pListener (pListener),
168         m_xAccRef( pAcc )
169 {
170     ImplInitializeCreateObj();
171 
172     m_xAccContextRef = m_xAccRef->getAccessibleContext();
173     m_xAccActionRef.set(m_xAccContextRef,UNO_QUERY);
174     m_accRole = m_xAccContextRef -> getAccessibleRole();
175     if( m_pIMAcc )
176     {
177         m_pIMAcc->SetXAccessible(reinterpret_cast<hyper>(m_xAccRef.get()));
178         m_pIMAcc->Put_XAccAgent(reinterpret_cast<hyper>(pAgent));
179         m_pIMAcc->SetDefaultAction(reinterpret_cast<hyper>(m_xAccActionRef.get()));
180     }
181 }
182 /**
183    * Destructor.
184    * @param
185    * @return
186    */
~AccObject()187 AccObject::~AccObject()
188 {
189     m_pIMAcc = nullptr;
190     m_xAccRef = nullptr;
191     m_xAccActionRef = nullptr;
192     m_xAccContextRef = nullptr;
193 }
194 
195 
196 /**
197    * Insert a child element.
198    * @param pChild Child element that should be inserted into child list.
199    * @param pos Insert position.
200    * @return
201    */
InsertChild(AccObject * pChild,short pos)202 void AccObject::InsertChild( AccObject* pChild,short pos )
203 {
204 
205     std::vector<AccObject*>::iterator iter;
206     iter = std::find(m_childrenList.begin(),m_childrenList.end(),pChild);
207     if(iter!=m_childrenList.end())
208         return;
209     if(LAST_CHILD==pos)
210     {
211         m_childrenList.push_back(pChild);
212     }
213     else
214     {
215         iter=m_childrenList.begin()+pos;
216         m_childrenList.insert(iter,pChild);
217     }
218 
219     pChild->SetParentObj(this);
220 }
221 
222 /**
223    * Delete a child element
224    * @param pChild Child element that should be inserted into child list.
225    * @param pos Insert position.
226    * @return
227    */
DeleteChild(AccObject * pChild)228 void AccObject::DeleteChild( AccObject* pChild )
229 {
230     std::vector<AccObject*>::iterator iter;
231     iter = std::find(m_childrenList.begin(),m_childrenList.end(),pChild);
232     if(iter!=m_childrenList.end())
233     {
234         m_childrenList.erase(iter);
235         if(m_pIMAcc)
236             pChild->SetParentObj(nullptr);
237     }
238 }
239 
240 /**
241    * In order to windows API WindowFromAccessibleObject, we sometimes to set a pure
242    * top window accessible object created by windows system as top ancestor.
243    * @param.
244    * @return
245    */
UpdateValidWindow()246 void AccObject::UpdateValidWindow()
247 {
248     if(m_pIMAcc)
249         m_pIMAcc->Put_XAccWindowHandle(m_pParantID);
250 }
251 
252 /**
253    * Translate all UNO basic information into MSAA com information.
254    * @param
255    * @return If the method is correctly processed.
256    */
ImplInitializeCreateObj()257 void AccObject::ImplInitializeCreateObj()
258 {
259     m_pIMAcc = UAccCOMCreateInstance();
260 
261     assert(m_pIMAcc);
262 }
263 
264 /**
265    * Update name property to com object.
266    * @param
267    * @return
268    */
UpdateName()269 void  AccObject::UpdateName( )
270 {
271     if (!m_pIMAcc)
272     {
273         return;
274     }
275 
276     if( ( TEXT_FRAME == m_accRole   ) && ( m_pParentObj !=nullptr )&& ( SCROLL_PANE == m_pParentObj -> m_accRole ) )
277         m_pIMAcc->Put_XAccName( o3tl::toW(m_pParentObj->m_xAccContextRef->getAccessibleName().getStr()) );
278     //IAccessibility2 Implementation 2009-----
279     if ( PARAGRAPH == m_accRole)
280     {
281         m_pIMAcc->Put_XAccName(L"");
282     }
283     //-----IAccessibility2 Implementation 2009
284     else
285         m_pIMAcc->Put_XAccName(o3tl::toW(m_xAccContextRef->getAccessibleName().getStr()));
286 
287     return ;
288 }
289 /**
290    * Update description property to com object.
291    * no content for update description
292    * @param
293    * @return
294    */
UpdateDescription()295 void AccObject::UpdateDescription()
296 {
297     if (!m_pIMAcc)
298     {
299         return;
300     }
301 
302     m_pIMAcc->Put_XAccDescription(o3tl::toW(m_xAccContextRef->getAccessibleDescription().getStr()));
303     return ;
304 }
305 
306 /**
307    * Update default action property to com object.
308    * @param
309    * @return
310    */
UpdateAction()311 void  AccObject::UpdateAction()
312 {
313     m_xAccActionRef.set(m_xAccContextRef,UNO_QUERY);
314 
315     if( m_xAccActionRef.is() && m_pIMAcc )
316     {
317         if( m_xAccActionRef->getAccessibleActionCount() > 0 )
318         {
319             UpdateDefaultAction( );
320             m_pIMAcc->SetDefaultAction(
321                     reinterpret_cast<hyper>(m_xAccActionRef.get()));
322         }
323     }
324 }
325 
326 /**
327    * Update value property to com object.
328    * @param
329    * @return
330    */
UpdateValue()331 void AccObject::UpdateValue()
332 {
333     if( nullptr == m_pIMAcc  || !m_xAccContextRef.is() )
334     {
335         assert(false);
336         return ;
337     }
338 
339     Reference< XAccessibleValue > pRValue(m_xAccContextRef,UNO_QUERY);
340     Any pAny;
341     if( pRValue.is() )
342     {
343         pAny = pRValue->getCurrentValue();
344     }
345 
346     SetValue( pAny );
347 }
348 
349 /**
350    * Set special default action description string via UNO role.
351    * @param Role UNO role
352    * @return
353    */
UpdateDefaultAction()354 void AccObject::UpdateDefaultAction( )
355 {
356     if(!m_xAccActionRef.is())
357         return ;
358 
359     switch(m_accRole)
360     {
361     case PUSH_BUTTON:
362     case TOGGLE_BUTTON:
363     case RADIO_BUTTON:
364     case MENU_ITEM:
365     case RADIO_MENU_ITEM:
366     case CHECK_MENU_ITEM:
367     case LIST_ITEM:
368     case CHECK_BOX:
369     case TREE_ITEM:
370     case BUTTON_DROPDOWN:
371         m_pIMAcc->Put_ActionDescription( o3tl::toW(m_xAccActionRef->getAccessibleActionDescription(sal_Int32(0)).getStr()) );
372         return;
373     }
374 }
375 
376 /**
377    * Set value property via pAny.
378    * @param pAny New value.
379    * @return
380    */
SetValue(Any pAny)381 void  AccObject::SetValue( Any pAny )
382 {
383     if( nullptr == m_pIMAcc || !m_xAccContextRef.is() )
384     {
385         assert(false);
386         return ;
387     }
388     Reference< XAccessibleText > pRText(m_xAccContextRef,UNO_QUERY);
389     OUString val;
390     switch(m_accRole)
391     {
392     case SPIN_BOX:
393         // 3. date editor's msaa value should be the same as spinbox
394     case DATE_EDITOR:
395     case TEXT:
396     case PARAGRAPH:
397     case HEADING:
398     case TABLE_CELL:
399 
400         if(pRText.get())
401         {
402             val = pRText->getText();
403         }
404         m_pIMAcc->Put_XAccValue( o3tl::toW(val.getStr()) );
405         break;
406     case TREE_ITEM:
407     //case CHECK_BOX:   //Commented by Li Xing to disable the value for general checkbox
408     case COMBO_BOX:
409     case NOTE:
410     case SCROLL_BAR:
411         m_pIMAcc->Put_XAccValue( o3tl::toW(GetMAccessibleValueFromAny(pAny).getStr()) );
412         break ;
413     // Added by Li Xing, only the checkbox in tree should have the value.
414     case CHECK_BOX:
415         if( ( m_pParentObj !=nullptr ) && (TREE == m_pParentObj->m_accRole || TREE_ITEM == m_pParentObj->m_accRole ))
416             m_pIMAcc->Put_XAccValue( o3tl::toW(GetMAccessibleValueFromAny(pAny).getStr()) );
417         break;
418     default:
419         break;
420     }
421 
422     return;
423 }
424 
GetMAccessibleValueFromAny(Any pAny)425 OUString AccObject::GetMAccessibleValueFromAny(Any pAny)
426 {
427     OUString strValue;
428 
429     if(nullptr == m_pIMAcc)
430         return strValue;
431 
432     if(pAny.getValueType() == cppu::UnoType<cppu::UnoUnsignedShortType>::get() )
433     {
434         sal_uInt16 val;
435         if (pAny >>= val)
436         {
437             strValue=OUString::number(val);
438 
439         }
440     }
441     else if(pAny.getValueType() == cppu::UnoType<OUString>::get())
442     {
443 
444         pAny >>= strValue ;
445 
446     }
447     else if(pAny.getValueType() == cppu::UnoType<Sequence< OUString >>::get())
448     {
449         Sequence< OUString > val;
450         if (pAny >>= val)
451         {
452 
453             int count = val.getLength();
454 
455             for( int iIndex = 0;iIndex < count;iIndex++ )
456             {
457                 strValue += val[iIndex];
458             }
459 
460         }
461     }
462     else if(pAny.getValueType() == cppu::UnoType<double>::get())
463     {
464         double val;
465         if (pAny >>= val)
466         {
467             strValue=OUString::number(val);
468         }
469     }
470     else if(pAny.getValueType() == cppu::UnoType<sal_Int32>::get())
471     {
472         sal_Int32 val;
473         if (pAny >>= val)
474         {
475             strValue=OUString::number(val);
476         }
477     }
478     else if (pAny.getValueType() == cppu::UnoType<css::accessibility::TextSegment>::get())
479     {
480         css::accessibility::TextSegment val;
481         if (pAny >>= val)
482         {
483             OUString realVal(val.SegmentText);
484             strValue = realVal;
485 
486         }
487     }
488 
489     return strValue;
490 }
491 /**
492    * Set name property via pAny.
493    * @param pAny New accessible name.
494    * @return
495    */
SetName(Any pAny)496 void  AccObject::SetName( Any pAny)
497 {
498     if( nullptr == m_pIMAcc )
499         return ;
500 
501     m_pIMAcc->Put_XAccName( o3tl::toW(GetMAccessibleValueFromAny(pAny).getStr()) );
502 
503 }
504 
505 /**
506    * Set description property via pAny.
507    * @param pAny New accessible description.
508    * @return
509    */
SetDescription(Any pAny)510 void  AccObject::SetDescription( Any pAny )
511 {
512     if( nullptr == m_pIMAcc )
513         return ;
514     m_pIMAcc->Put_XAccDescription( o3tl::toW(GetMAccessibleValueFromAny(pAny).getStr()) );
515 }
516 
517 /**
518    * Set role property via pAny
519    * @param Role New accessible role.
520    * @return
521    */
SetRole(short Role)522 void  AccObject::SetRole( short Role )
523 {
524     if( nullptr == m_pIMAcc )
525         return ;
526     m_pIMAcc->Put_XAccRole( Role );
527 }
528 
529 /**
530 * Get role property via pAny
531 * @param
532 * @return accessible role
533 */
GetRole() const534 short AccObject::GetRole() const
535 {
536     return m_accRole;
537 }
538 
539 /**
540    * Get MSAA state from UNO state
541    * @Role xState UNO state.
542    * @return
543    */
GetMSAAStateFromUNO(short xState)544 DWORD AccObject::GetMSAAStateFromUNO(short xState)
545 {
546     DWORD IState = UNO_MSAA_UNMAPPING;
547 
548     if( !m_xAccContextRef.is() )
549     {
550         assert(false);
551         return IState;
552     }
553     short Role = m_accRole;
554 
555     switch( xState )
556     {
557     case  BUSY:
558         IState = STATE_SYSTEM_BUSY;
559         break;
560     case  CHECKED:
561         if( Role == PUSH_BUTTON || Role == TOGGLE_BUTTON )
562         {
563             IState = STATE_SYSTEM_PRESSED;
564         }
565         else
566             IState = STATE_SYSTEM_CHECKED;
567         break;
568     case  DEFUNC:
569         IState = STATE_SYSTEM_UNAVAILABLE;
570         break;
571     case  EXPANDED:
572         IState = STATE_SYSTEM_EXPANDED;
573         break;
574     case  FOCUSABLE:
575         IState = STATE_SYSTEM_FOCUSABLE;
576         break;
577     case  FOCUSED:
578         IState = STATE_SYSTEM_FOCUSED;
579         break;
580     case  INDETERMINATE:
581         IState = STATE_SYSTEM_MIXED;
582         break;
583     case  MULTI_SELECTABLE:
584         IState = STATE_SYSTEM_MULTISELECTABLE;
585         break;
586     case  PRESSED:
587         IState = STATE_SYSTEM_PRESSED;
588         break;
589     case  RESIZABLE:
590         IState = STATE_SYSTEM_SIZEABLE;
591         break;
592     case  SELECTABLE:
593         if( m_accRole == MENU || m_accRole == MENU_ITEM)
594         {
595             IState = UNO_MSAA_UNMAPPING;
596         }
597         else
598         {
599             IState = STATE_SYSTEM_SELECTABLE;
600         }
601         break;
602     case  SELECTED:
603         if( m_accRole == MENU || m_accRole == MENU_ITEM )
604         {
605             IState = UNO_MSAA_UNMAPPING;
606         }
607         else
608         {
609             IState = STATE_SYSTEM_SELECTED;
610         }
611         break;
612     case  ARMED:
613         IState = STATE_SYSTEM_FOCUSED;
614         break;
615     case  EXPANDABLE:
616         {
617             sal_Bool isExpanded = true;
618             sal_Bool isExpandable = true;
619             if( Role == PUSH_BUTTON || Role == TOGGLE_BUTTON  || BUTTON_DROPDOWN == Role )
620             {
621                 IState = STATE_SYSTEM_HASPOPUP;
622             }
623             else
624             {
625                 GetExpandedState(&isExpandable,&isExpanded);
626                 if(!isExpanded)
627                     IState = STATE_SYSTEM_COLLAPSED;
628             }
629         }
630         break;
631     //Remove the SENSITIVE state mapping. There is no corresponding MSAA state.
632     //case  SENSITIVE:
633     //    IState = STATE_SYSTEM_PROTECTED;
634     case EDITABLE:
635         if( m_pIMAcc )
636         {
637             m_pIMAcc->DecreaseState( STATE_SYSTEM_READONLY );
638         }
639         break;
640     case OFFSCREEN:
641         IState = STATE_SYSTEM_OFFSCREEN;
642         break;
643     case MOVEABLE:
644         IState = STATE_SYSTEM_MOVEABLE;
645         break;
646     case COLLAPSE:
647         IState = STATE_SYSTEM_COLLAPSED;
648         break;
649     case DEFAULT:
650         IState = STATE_SYSTEM_DEFAULT;
651         break;
652     default:
653         break;
654     }
655 
656     return IState;
657 }
658 
659 /**
660    * Decrease state of com object
661    * @param xState The lost state.
662    * @return
663    */
DecreaseState(short xState)664 void  AccObject::DecreaseState( short xState )
665 {
666     if( nullptr == m_pIMAcc )
667     {
668         return;
669     }
670 
671     if( xState == FOCUSABLE)
672     {
673         short Role = m_accRole ;
674         if(Role == MENU_ITEM
675                 || Role == RADIO_MENU_ITEM
676                 || Role == CHECK_MENU_ITEM)
677             return;
678         else
679         {
680             if (Role == TOGGLE_BUTTON || Role == PUSH_BUTTON || BUTTON_DROPDOWN == Role)
681             {
682                 if( ( m_pParentObj !=nullptr ) && (TOOL_BAR == m_pParentObj->m_accRole ) )
683                     return;
684             }
685         }
686     }
687 
688     else if( xState == AccessibleStateType::VISIBLE  )
689     {
690         m_pIMAcc->IncreaseState( STATE_SYSTEM_INVISIBLE );
691     }
692     else if( xState == AccessibleStateType::SHOWING )
693     {
694         m_pIMAcc->IncreaseState( STATE_SYSTEM_OFFSCREEN );
695     }
696 
697     DWORD msState = GetMSAAStateFromUNO(xState);
698     if(msState!=UNO_MSAA_UNMAPPING)
699         m_pIMAcc->DecreaseState(msState);
700 }
701 
702 /**
703    * Increase state of com object
704    * @param xState The new state.
705    * @return
706    */
IncreaseState(short xState)707 void AccObject::IncreaseState( short xState )
708 {
709     if( nullptr == m_pIMAcc )
710     {
711         assert(false);
712         return;
713     }
714 
715 
716     if( xState == AccessibleStateType::VISIBLE  )
717     {
718         m_pIMAcc->DecreaseState( STATE_SYSTEM_INVISIBLE );
719     }
720     else if( xState == AccessibleStateType::SHOWING )
721     {
722         m_pIMAcc->DecreaseState( STATE_SYSTEM_OFFSCREEN );
723     }
724 
725 
726     DWORD msState = GetMSAAStateFromUNO(xState);
727     if(msState!=UNO_MSAA_UNMAPPING)
728         m_pIMAcc->IncreaseState( msState );
729 }
730 
731 /**
732    * Get next child element
733    * @param
734    * @return AccObject Object interface.
735    */
NextChild()736 AccObject* AccObject::NextChild()
737 {
738     IAccChildList::iterator pInd = m_childrenList.begin();
739     if( pInd != m_childrenList.end() )
740         return  *pInd;
741     return nullptr;
742 }
743 /**
744    * update action description desc
745    * @param
746    * @return
747    */
UpdateActionDesc()748 void AccObject::UpdateActionDesc()
749 {
750     if (!m_pIMAcc)
751     {
752         return;
753     }
754 
755     OUString pXString = m_xAccContextRef->getAccessibleDescription();
756     m_pIMAcc->Put_XAccDescription(o3tl::toW(pXString.getStr()));
757     long Role = m_accRole;
758 
759     if(  Role == PUSH_BUTTON || Role == RADIO_BUTTON || Role == MENU_ITEM ||
760             Role == LIST_ITEM || Role == CHECK_BOX || Role == TREE_ITEM ||
761             Role == CHECK_MENU_ITEM || Role == RADIO_MENU_ITEM )
762     {
763         UpdateDefaultAction(  );
764     }
765     else
766     {
767 
768         if( m_xAccActionRef.is() )
769         {
770             if( m_xAccActionRef->getAccessibleActionCount() > 0 )
771             {
772                 if (!(Role == SPIN_BOX || Role == COMBO_BOX || Role == DATE_EDITOR ||
773                       Role == EDIT_BAR || Role == PASSWORD_TEXT || Role == TEXT))
774                 {
775                     pXString = m_xAccActionRef->getAccessibleActionDescription( 0 );
776                     //Solution: if string length is more than zero, action is set.
777                     if( pXString.getLength() > 0)
778                         m_pIMAcc->Put_ActionDescription( o3tl::toW(pXString.getStr()) );
779                 }
780             }
781         }
782     }
783 
784 }
785 /**
786    * update role information from uno to com
787    * @param
788    * @return
789    */
UpdateRole()790 void AccObject::UpdateRole()
791 {
792     if (!m_pIMAcc)
793     {
794         return;
795     }
796 
797     XAccessibleContext* pContext  = m_xAccContextRef.get();
798     m_pIMAcc->Put_XAccRole( ROLE_SYSTEM_WINDOW  );
799     sal_Int16 iRoleIndex = pContext->getAccessibleRole();
800     if ((0 <= iRoleIndex) && (sal_uInt16(iRoleIndex) < SAL_N_ELEMENTS(ROLE_TABLE)))
801     {
802         short iIA2Role = ROLE_TABLE[iRoleIndex][1] ;
803         m_pIMAcc->Put_XAccRole( iIA2Role  );
804     }
805 
806 }
807 /**
808    * update state information from uno to com
809    * @param
810    * @return
811    */
UpdateState()812 void AccObject::UpdateState()
813 {
814     if (!m_pIMAcc)
815     {
816         return;
817     }
818 
819     XAccessibleContext* pContext  = m_xAccContextRef.get();
820     Reference< XAccessibleStateSet > pRState = pContext->getAccessibleStateSet();
821     if( !pRState.is() )
822     {
823         assert(false);
824         return ;
825     }
826 
827     m_pIMAcc->SetState(0);
828 
829     if ( m_accRole == POPUP_MENU )
830     {
831         return;
832     }
833 
834     Sequence<short> pStates = pRState->getStates();
835     int count = pStates.getLength();
836 
837     bool isEnable = false;
838     bool isShowing = false;
839     bool isEditable = false;
840     bool isVisible = false;
841     bool isFocusable = false;
842 
843     for( int iIndex = 0;iIndex < count;iIndex++ )
844     {
845         if( pStates[iIndex] == ENABLED )
846             isEnable = true;
847         else if( pStates[iIndex] == SHOWING)
848             isShowing = true;
849         else if( pStates[iIndex] == VISIBLE)
850             isVisible = true;
851         else if( pStates[iIndex] == EDITABLE )
852             isEditable = true;
853         else if (pStates[iIndex] == FOCUSABLE)
854             isFocusable = true;
855         IncreaseState( pStates[iIndex]);
856     }
857     bool bIsMenuItem = m_accRole == MENU_ITEM || m_accRole == RADIO_MENU_ITEM || m_accRole == CHECK_MENU_ITEM;
858 
859     if(bIsMenuItem)
860     {
861         if(!(isShowing && isVisible) )
862         {
863             m_pIMAcc->IncreaseState( STATE_SYSTEM_INVISIBLE );
864             m_pIMAcc->DecreaseState( STATE_SYSTEM_FOCUSABLE );
865         }
866     }
867     else
868     {
869         if(!(isShowing || isVisible) )
870             m_pIMAcc->IncreaseState( STATE_SYSTEM_INVISIBLE );
871     }
872 
873     short Role = m_accRole;
874 
875     switch(m_accRole)
876     {
877     case LABEL:
878     case STATIC:
879         m_pIMAcc->IncreaseState( STATE_SYSTEM_READONLY );
880         break;
881     case TEXT:
882         // 2. editable combobox -> readonly ------ bridge
883     case EMBEDDED_OBJECT:
884     case END_NOTE:
885     case FOOTER:
886     case FOOTNOTE:
887     case GRAPHIC:
888     case HEADER:
889     case HEADING:
890 
891         //Image Map
892     case PARAGRAPH:
893     case PASSWORD_TEXT:
894     case SHAPE:
895     case SPIN_BOX:
896     case TABLE:
897     case TABLE_CELL:
898     case TEXT_FRAME:
899     case DATE_EDITOR:
900     case DOCUMENT:
901     case COLUMN_HEADER:
902         {
903             if(!isEditable)
904                 m_pIMAcc->IncreaseState( STATE_SYSTEM_READONLY );
905         }
906         break;
907     default:
908         break;
909     }
910 
911     if( isEnable )
912     {
913 
914         if(!(Role == FILLER || Role == END_NOTE || Role == FOOTER || Role == FOOTNOTE || Role == GROUP_BOX || Role == RULER
915                 || Role == HEADER || Role == ICON || Role == INTERNAL_FRAME || Role == LABEL || Role == LAYERED_PANE
916                 || Role == SCROLL_BAR || Role == SCROLL_PANE || Role == SPLIT_PANE || Role == STATIC || Role == STATUS_BAR
917                 || Role == TOOL_TIP))
918         {
919             if( SEPARATOR == Role  )
920             {
921                 if( ( m_pParentObj != nullptr ) && ( MENU == m_pParentObj->m_accRole  || POPUP_MENU == m_pParentObj->m_accRole ))
922                     IncreaseState( FOCUSABLE );
923             }
924 
925             else if (TABLE_CELL == Role || TABLE == Role || PANEL == Role || OPTION_PANE == Role ||
926                      COLUMN_HEADER == Role)
927             {
928                 if (isFocusable)
929                     IncreaseState( FOCUSABLE );
930             }
931             else
932             {
933                 if(bIsMenuItem)
934                 {
935                     if ( isShowing && isVisible)
936                     {
937                         IncreaseState( FOCUSABLE );
938                     }
939                 }
940                 else
941                 {
942                     IncreaseState( FOCUSABLE );
943                 }
944             }
945         }
946     }
947     else
948     {
949         m_pIMAcc->IncreaseState( STATE_SYSTEM_UNAVAILABLE );
950         if( !((Role == MENU_ITEM) ||
951                 (Role == RADIO_MENU_ITEM) ||
952                 (Role == CHECK_MENU_ITEM)) )
953         {
954             if  ( Role == TOGGLE_BUTTON || Role == PUSH_BUTTON || BUTTON_DROPDOWN == Role)
955             {
956                 if(( m_pParentObj != nullptr )&& (TOOL_BAR ==  m_pParentObj->m_accRole ) )
957                     IncreaseState( FOCUSABLE );
958                 else
959                     DecreaseState( FOCUSABLE );
960             }
961             else
962                 DecreaseState( FOCUSABLE );
963         }
964         else if( isShowing || isVisible )
965         {
966             IncreaseState( FOCUSABLE );
967         }
968     }
969 
970     switch(m_accRole)
971     {
972     case POPUP_MENU:
973     case MENU:
974         if( pContext->getAccessibleChildCount() > 0 )
975             m_pIMAcc->IncreaseState( STATE_SYSTEM_HASPOPUP );
976         break;
977     case PASSWORD_TEXT:
978         m_pIMAcc->IncreaseState( STATE_SYSTEM_PROTECTED );
979         break;
980     default:
981         break;
982     }
983 }
984 
985 /**
986    * update location information from uno to com
987    * @param
988    * @return
989    */
UpdateLocation()990 void AccObject::UpdateLocation()
991 {
992     if (!m_pIMAcc)
993     {
994         return;
995     }
996     XAccessibleContext* pContext  = m_xAccContextRef.get();
997 
998     Reference< XAccessibleComponent > pRComponent(pContext,UNO_QUERY);
999     if( pRComponent.is() )
1000     {
1001         css::awt::Point pCPoint = pRComponent->getLocationOnScreen();
1002         css::awt::Size pCSize = pRComponent->getSize();
1003         Location tempLocation;
1004         tempLocation.m_dLeft = pCPoint.X;
1005         tempLocation.m_dTop =  pCPoint.Y;
1006         tempLocation.m_dWidth = pCSize.Width;
1007         tempLocation.m_dHeight = pCSize.Height;
1008         m_pIMAcc->Put_XAccLocation( tempLocation );
1009     }
1010 
1011 }
1012 
1013 
1014 /**
1015    * Public method to mapping information between MSAA and UNO.
1016    * @param
1017    * @return If the method is correctly processed.
1018    */
UpdateAccessibleInfoFromUnoToMSAA()1019 bool AccObject:: UpdateAccessibleInfoFromUnoToMSAA ( )
1020 {
1021     if( nullptr == m_pIMAcc || !m_xAccContextRef.is()  )
1022     {
1023         assert(false);
1024         return false;
1025     }
1026 
1027     UpdateName();
1028 
1029     UpdateValue();
1030 
1031     UpdateActionDesc();
1032 
1033     UpdateRole();
1034 
1035     UpdateLocation();
1036 
1037     UpdateState();
1038 
1039     return true;
1040 }
1041 
1042 /*
1043    * Add a child selected element.
1044    * @param pAccObj Child object pointer.
1045    * @return
1046    */
AddSelect(long index,AccObject * accObj)1047 void AccObject::AddSelect( long index, AccObject* accObj)
1048 {
1049     m_selectionList.emplace(index,accObj);
1050 }
1051 
GetSelection()1052 IAccSelectionList& AccObject::GetSelection()
1053 {
1054     return m_selectionList;
1055 }
1056 
1057 
1058 /**
1059    * Set self to focus object in parent child list
1060    * @param
1061    * @return
1062    */
setFocus()1063 void AccObject::setFocus()
1064 {
1065     if(m_pIMAcc)
1066     {
1067         IncreaseState(FOCUSED);
1068         m_pIMAcc->Put_XAccFocus(CHILDID_SELF);
1069 
1070         UpdateRole();
1071     }
1072 }
1073 
1074 /**
1075    * Unset self from focus object in parent child list.
1076    * @param
1077    * @return
1078    */
unsetFocus()1079 void AccObject::unsetFocus()
1080 {
1081     if(m_pIMAcc)
1082     {
1083         DecreaseState( FOCUSED );
1084         m_pIMAcc->Put_XAccFocus(UACC_NO_FOCUS);
1085     }
1086 }
1087 
GetExpandedState(sal_Bool * isExpandable,sal_Bool * isExpanded)1088 void AccObject::GetExpandedState( sal_Bool* isExpandable, sal_Bool* isExpanded)
1089 {
1090     *isExpanded = false;
1091     *isExpandable = false;
1092 
1093     if( !m_xAccContextRef.is() )
1094     {
1095         return;
1096     }
1097     Reference< XAccessibleStateSet > pRState = m_xAccContextRef->getAccessibleStateSet();
1098     if( !pRState.is() )
1099     {
1100         return;
1101     }
1102 
1103     Sequence<short> pStates = pRState->getStates();
1104     int count = pStates.getLength();
1105 
1106     for( int iIndex = 0;iIndex < count;iIndex++ )
1107     {
1108         if( EXPANDED == pStates[iIndex]  )
1109         {
1110             *isExpanded = true;
1111         }
1112         else if( EXPANDABLE == pStates[iIndex]  )
1113         {
1114             *isExpandable = true;
1115         }
1116     }
1117 }
1118 
NotifyDestroy(bool ifDelete)1119 void AccObject::NotifyDestroy(bool ifDelete)
1120 {
1121     m_bShouldDestroy=ifDelete;
1122     if(m_pIMAcc)
1123         m_pIMAcc->NotifyDestroy(m_bShouldDestroy);
1124 }
1125 
SetParentObj(AccObject * pParentAccObj)1126 void AccObject::SetParentObj(AccObject* pParentAccObj)
1127 {
1128     m_pParentObj = pParentAccObj;
1129 
1130     if(m_pIMAcc)
1131     {
1132         if(m_pParentObj)
1133         {
1134             m_pIMAcc->Put_XAccParent(m_pParentObj->GetIMAccessible());
1135         }
1136         else
1137         {
1138             m_pIMAcc->Put_XAccParent(nullptr);
1139         }
1140     }
1141 }
1142 //ResID means ChildID in MSAA
SetResID(long id)1143 void AccObject::SetResID(long id)
1144 {
1145     m_resID = id;
1146     if(m_pIMAcc)
1147         m_pIMAcc->Put_XAccChildID(m_resID);
1148 }
1149 //return COM interface in acc object
GetIMAccessible()1150 IMAccessible*  AccObject::GetIMAccessible()
1151 {
1152     return m_pIMAcc;
1153 }
1154 
GetXAccessible()1155 Reference<XAccessible> const& AccObject::GetXAccessible()
1156 {
1157     return m_xAccRef;
1158 }
1159 
SetParentHWND(HWND hWnd)1160 void AccObject::SetParentHWND(HWND hWnd)
1161 {
1162     m_pParantID = hWnd;
1163 }
1164 
SetListener(rtl::Reference<AccEventListener> const & pListener)1165 void AccObject::SetListener(rtl::Reference<AccEventListener> const& pListener)
1166 {
1167     m_pListener = pListener;
1168 }
1169 
getListener()1170 AccEventListener* AccObject::getListener()
1171 {
1172     return m_pListener.get();
1173 }
1174 
GetResID()1175 long AccObject::GetResID()
1176 {
1177     return m_resID;
1178 }
1179 
GetParentHWND()1180 HWND AccObject::GetParentHWND()
1181 {
1182     return m_pParantID;
1183 }
1184 
GetParentObj()1185 AccObject* AccObject::GetParentObj()
1186 {
1187     return m_pParentObj;
1188 }
ifShouldDestroy()1189 bool  AccObject::ifShouldDestroy()
1190 {
1191     return m_bShouldDestroy;
1192 }
1193 
1194 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1195