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