bump product version to 7.6.3.2-android
[LibreOffice.git] / test / source / a11y / AccessibilityTools.cxx
blob33270505f3a6f762e912bf62a0b3ffe637c081ba
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <test/a11y/AccessibilityTools.hxx>
22 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
23 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
24 #include <com/sun/star/accessibility/AccessibleRole.hpp>
25 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
26 #include <com/sun/star/accessibility/XAccessible.hpp>
27 #include <com/sun/star/accessibility/XAccessibleAction.hpp>
28 #include <com/sun/star/accessibility/XAccessibleContext.hpp>
29 #include <com/sun/star/awt/KeyModifier.hpp>
31 #include <rtl/ustrbuf.hxx>
32 #include <sal/log.hxx>
33 #include <toolkit/awt/vclxaccessiblecomponent.hxx>
34 #include <vcl/scheduler.hxx>
35 #include <vcl/timer.hxx>
36 #include <vcl/window.hxx>
37 #include <o3tl/string_view.hxx>
39 using namespace css;
41 uno::Reference<accessibility::XAccessibleContext>
42 AccessibilityTools::getAccessibleObjectForPredicate(
43 const uno::Reference<accessibility::XAccessibleContext>& xCtx,
44 const std::function<bool(const uno::Reference<accessibility::XAccessibleContext>&)>& cPredicate)
46 if (cPredicate(xCtx))
48 return xCtx;
50 else
52 sal_Int64 count = xCtx->getAccessibleChildCount();
54 for (sal_Int64 i = 0; i < count && i < AccessibilityTools::MAX_CHILDREN; i++)
56 uno::Reference<accessibility::XAccessibleContext> xCtx2
57 = getAccessibleObjectForPredicate(xCtx->getAccessibleChild(i), cPredicate);
58 if (xCtx2.is())
59 return xCtx2;
62 return nullptr;
65 uno::Reference<accessibility::XAccessibleContext>
66 AccessibilityTools::getAccessibleObjectForPredicate(
67 const uno::Reference<accessibility::XAccessible>& xAcc,
68 const std::function<bool(const uno::Reference<accessibility::XAccessibleContext>&)>& cPredicate)
70 return getAccessibleObjectForPredicate(xAcc->getAccessibleContext(), cPredicate);
73 uno::Reference<accessibility::XAccessibleContext> AccessibilityTools::getAccessibleObjectForRole(
74 const uno::Reference<accessibility::XAccessibleContext>& xCtx, sal_Int16 role)
76 return getAccessibleObjectForPredicate(
77 xCtx, [&role](const uno::Reference<accessibility::XAccessibleContext>& xObjCtx) {
78 return (xObjCtx->getAccessibleRole() == role
79 && xObjCtx->getAccessibleStateSet()
80 & accessibility::AccessibleStateType::SHOWING);
81 });
84 css::uno::Reference<css::accessibility::XAccessibleContext>
85 AccessibilityTools::getAccessibleObjectForRole(
86 const css::uno::Reference<css::accessibility::XAccessible>& xacc, sal_Int16 role)
88 return getAccessibleObjectForRole(xacc->getAccessibleContext(), role);
91 /* this is basically the same as getAccessibleObjectForPredicate() but specialized for efficiency,
92 * and because the template version will not work with getAccessibleObjectForPredicate() anyway */
93 css::uno::Reference<css::accessibility::XAccessibleContext>
94 AccessibilityTools::getAccessibleObjectForName(
95 const css::uno::Reference<css::accessibility::XAccessibleContext>& xCtx, const sal_Int16 role,
96 std::u16string_view name)
98 if (xCtx->getAccessibleRole() == role && nameEquals(xCtx, name))
99 return xCtx;
101 auto nChildren = xCtx->getAccessibleChildCount();
102 for (decltype(nChildren) i = 0; i < nChildren && i < AccessibilityTools::MAX_CHILDREN; i++)
104 if (auto xMatchChild = getAccessibleObjectForName(xCtx->getAccessibleChild(i), role, name))
105 return xMatchChild;
108 return nullptr;
111 bool AccessibilityTools::equals(const uno::Reference<accessibility::XAccessible>& xacc1,
112 const uno::Reference<accessibility::XAccessible>& xacc2)
114 if (!xacc1.is() || !xacc2.is())
115 return xacc1.is() == xacc2.is();
116 return equals(xacc1->getAccessibleContext(), xacc2->getAccessibleContext());
119 bool AccessibilityTools::equals(const uno::Reference<accessibility::XAccessibleContext>& xctx1,
120 const uno::Reference<accessibility::XAccessibleContext>& xctx2)
122 if (!xctx1.is() || !xctx2.is())
123 return xctx1.is() == xctx2.is();
125 if (xctx1->getAccessibleRole() != xctx2->getAccessibleRole())
126 return false;
128 if (xctx1->getAccessibleName() != xctx2->getAccessibleName())
129 return false;
131 if (xctx1->getAccessibleDescription() != xctx2->getAccessibleDescription())
132 return false;
134 if (xctx1->getAccessibleChildCount() != xctx2->getAccessibleChildCount())
135 return false;
137 /* this one was not in the Java version */
138 if (xctx1->getAccessibleIndexInParent() != xctx2->getAccessibleIndexInParent())
139 return false;
141 /* because in Writer at least some children only are referenced by their relations to others
142 * objects, we need to account for that as their index in parent is incorrect (so not
143 * necessarily unique) */
144 auto relset1 = xctx1->getAccessibleRelationSet();
145 auto relset2 = xctx2->getAccessibleRelationSet();
146 if (relset1.is() != relset2.is())
147 return false;
148 else if (relset1.is())
150 auto relCount1 = relset1->getRelationCount();
151 auto relCount2 = relset2->getRelationCount();
152 if (relCount1 != relCount2)
153 return false;
155 for (sal_Int32 i = 0; i < relCount1; ++i)
157 if (relset1->getRelation(i) != relset2->getRelation(i))
158 return false;
162 return equals(xctx1->getAccessibleParent(), xctx2->getAccessibleParent());
165 bool AccessibilityTools::nameEquals(const uno::Reference<accessibility::XAccessibleContext>& xCtx,
166 const std::u16string_view name)
168 auto ctxName = xCtx->getAccessibleName();
169 std::u16string_view rest;
171 if (!o3tl::starts_with(ctxName, name, &rest))
172 return false;
173 if (rest == u"")
174 return true;
176 #if defined(_WIN32)
177 // see OAccessibleMenuItemComponent::GetAccessibleName():
178 // on Win32, ignore a \tSHORTCUT suffix on a menu item
179 switch (xCtx->getAccessibleRole())
181 case accessibility::AccessibleRole::MENU_ITEM:
182 case accessibility::AccessibleRole::RADIO_MENU_ITEM:
183 case accessibility::AccessibleRole::CHECK_MENU_ITEM:
184 return rest[0] == '\t';
186 default:
187 break;
189 #endif
191 #if OSL_DEBUG_LEVEL > 0
192 // see VCLXAccessibleComponent::getAccessibleName()
193 auto pVCLXAccessibleComponent = dynamic_cast<VCLXAccessibleComponent*>(xCtx.get());
194 if (pVCLXAccessibleComponent)
196 auto windowType = pVCLXAccessibleComponent->GetWindow()->GetType();
197 if (rest
198 == Concat2View(u" (Type = " + OUString::number(static_cast<sal_Int32>(windowType))
199 + ")"))
200 return true;
202 #endif
203 return false;
206 static OUString unknownName(const sal_Int64 value)
208 return "unknown (" + OUString::number(value) + ")";
211 OUString AccessibilityTools::getRoleName(const sal_Int16 role)
213 switch (role)
215 case accessibility::AccessibleRole::UNKNOWN:
216 return "UNKNOWN";
217 case accessibility::AccessibleRole::ALERT:
218 return "ALERT";
219 case accessibility::AccessibleRole::BUTTON_DROPDOWN:
220 return "BUTTON_DROPDOWN";
221 case accessibility::AccessibleRole::BUTTON_MENU:
222 return "BUTTON_MENU";
223 case accessibility::AccessibleRole::CANVAS:
224 return "CANVAS";
225 case accessibility::AccessibleRole::CAPTION:
226 return "CAPTION";
227 case accessibility::AccessibleRole::CHART:
228 return "CHART";
229 case accessibility::AccessibleRole::CHECK_BOX:
230 return "CHECK_BOX";
231 case accessibility::AccessibleRole::CHECK_MENU_ITEM:
232 return "CHECK_MENU_ITEM";
233 case accessibility::AccessibleRole::COLOR_CHOOSER:
234 return "COLOR_CHOOSER";
235 case accessibility::AccessibleRole::COLUMN_HEADER:
236 return "COLUMN_HEADER";
237 case accessibility::AccessibleRole::COMBO_BOX:
238 return "COMBO_BOX";
239 case accessibility::AccessibleRole::COMMENT:
240 return "COMMENT";
241 case accessibility::AccessibleRole::COMMENT_END:
242 return "COMMENT_END";
243 case accessibility::AccessibleRole::DATE_EDITOR:
244 return "DATE_EDITOR";
245 case accessibility::AccessibleRole::DESKTOP_ICON:
246 return "DESKTOP_ICON";
247 case accessibility::AccessibleRole::DESKTOP_PANE:
248 return "DESKTOP_PANE";
249 case accessibility::AccessibleRole::DIALOG:
250 return "DIALOG";
251 case accessibility::AccessibleRole::DIRECTORY_PANE:
252 return "DIRECTORY_PANE";
253 case accessibility::AccessibleRole::DOCUMENT:
254 return "DOCUMENT";
255 case accessibility::AccessibleRole::DOCUMENT_PRESENTATION:
256 return "DOCUMENT_PRESENTATION";
257 case accessibility::AccessibleRole::DOCUMENT_SPREADSHEET:
258 return "DOCUMENT_SPREADSHEET";
259 case accessibility::AccessibleRole::DOCUMENT_TEXT:
260 return "DOCUMENT_TEXT";
261 case accessibility::AccessibleRole::EDIT_BAR:
262 return "EDIT_BAR";
263 case accessibility::AccessibleRole::EMBEDDED_OBJECT:
264 return "EMBEDDED_OBJECT";
265 case accessibility::AccessibleRole::END_NOTE:
266 return "END_NOTE";
267 case accessibility::AccessibleRole::FILE_CHOOSER:
268 return "FILE_CHOOSER";
269 case accessibility::AccessibleRole::FILLER:
270 return "FILLER";
271 case accessibility::AccessibleRole::FONT_CHOOSER:
272 return "FONT_CHOOSER";
273 case accessibility::AccessibleRole::FOOTER:
274 return "FOOTER";
275 case accessibility::AccessibleRole::FOOTNOTE:
276 return "FOOTNOTE";
277 case accessibility::AccessibleRole::FORM:
278 return "FORM";
279 case accessibility::AccessibleRole::FRAME:
280 return "FRAME";
281 case accessibility::AccessibleRole::GLASS_PANE:
282 return "GLASS_PANE";
283 case accessibility::AccessibleRole::GRAPHIC:
284 return "GRAPHIC";
285 case accessibility::AccessibleRole::GROUP_BOX:
286 return "GROUP_BOX";
287 case accessibility::AccessibleRole::HEADER:
288 return "HEADER";
289 case accessibility::AccessibleRole::HEADING:
290 return "HEADING";
291 case accessibility::AccessibleRole::HYPER_LINK:
292 return "HYPER_LINK";
293 case accessibility::AccessibleRole::ICON:
294 return "ICON";
295 case accessibility::AccessibleRole::IMAGE_MAP:
296 return "IMAGE_MAP";
297 case accessibility::AccessibleRole::INTERNAL_FRAME:
298 return "INTERNAL_FRAME";
299 case accessibility::AccessibleRole::LABEL:
300 return "LABEL";
301 case accessibility::AccessibleRole::LAYERED_PANE:
302 return "LAYERED_PANE";
303 case accessibility::AccessibleRole::LIST:
304 return "LIST";
305 case accessibility::AccessibleRole::LIST_ITEM:
306 return "LIST_ITEM";
307 case accessibility::AccessibleRole::MENU:
308 return "MENU";
309 case accessibility::AccessibleRole::MENU_BAR:
310 return "MENU_BAR";
311 case accessibility::AccessibleRole::MENU_ITEM:
312 return "MENU_ITEM";
313 case accessibility::AccessibleRole::NOTE:
314 return "NOTE";
315 case accessibility::AccessibleRole::OPTION_PANE:
316 return "OPTION_PANE";
317 case accessibility::AccessibleRole::PAGE:
318 return "PAGE";
319 case accessibility::AccessibleRole::PAGE_TAB:
320 return "PAGE_TAB";
321 case accessibility::AccessibleRole::PAGE_TAB_LIST:
322 return "PAGE_TAB_LIST";
323 case accessibility::AccessibleRole::PANEL:
324 return "PANEL";
325 case accessibility::AccessibleRole::PARAGRAPH:
326 return "PARAGRAPH";
327 case accessibility::AccessibleRole::PASSWORD_TEXT:
328 return "PASSWORD_TEXT";
329 case accessibility::AccessibleRole::POPUP_MENU:
330 return "POPUP_MENU";
331 case accessibility::AccessibleRole::PROGRESS_BAR:
332 return "PROGRESS_BAR";
333 case accessibility::AccessibleRole::PUSH_BUTTON:
334 return "PUSH_BUTTON";
335 case accessibility::AccessibleRole::RADIO_BUTTON:
336 return "RADIO_BUTTON";
337 case accessibility::AccessibleRole::RADIO_MENU_ITEM:
338 return "RADIO_MENU_ITEM";
339 case accessibility::AccessibleRole::ROOT_PANE:
340 return "ROOT_PANE";
341 case accessibility::AccessibleRole::ROW_HEADER:
342 return "ROW_HEADER";
343 case accessibility::AccessibleRole::RULER:
344 return "RULER";
345 case accessibility::AccessibleRole::SCROLL_BAR:
346 return "SCROLL_BAR";
347 case accessibility::AccessibleRole::SCROLL_PANE:
348 return "SCROLL_PANE";
349 case accessibility::AccessibleRole::SECTION:
350 return "SECTION";
351 case accessibility::AccessibleRole::SEPARATOR:
352 return "SEPARATOR";
353 case accessibility::AccessibleRole::SHAPE:
354 return "SHAPE";
355 case accessibility::AccessibleRole::SLIDER:
356 return "SLIDER";
357 case accessibility::AccessibleRole::SPIN_BOX:
358 return "SPIN_BOX";
359 case accessibility::AccessibleRole::SPLIT_PANE:
360 return "SPLIT_PANE";
361 case accessibility::AccessibleRole::STATIC:
362 return "STATIC";
363 case accessibility::AccessibleRole::STATUS_BAR:
364 return "STATUS_BAR";
365 case accessibility::AccessibleRole::TABLE:
366 return "TABLE";
367 case accessibility::AccessibleRole::TABLE_CELL:
368 return "TABLE_CELL";
369 case accessibility::AccessibleRole::TEXT:
370 return "TEXT";
371 case accessibility::AccessibleRole::TEXT_FRAME:
372 return "TEXT_FRAME";
373 case accessibility::AccessibleRole::TOGGLE_BUTTON:
374 return "TOGGLE_BUTTON";
375 case accessibility::AccessibleRole::TOOL_BAR:
376 return "TOOL_BAR";
377 case accessibility::AccessibleRole::TOOL_TIP:
378 return "TOOL_TIP";
379 case accessibility::AccessibleRole::TREE:
380 return "TREE";
381 case accessibility::AccessibleRole::TREE_ITEM:
382 return "TREE_ITEM";
383 case accessibility::AccessibleRole::TREE_TABLE:
384 return "TREE_TABLE";
385 case accessibility::AccessibleRole::VIEW_PORT:
386 return "VIEW_PORT";
387 case accessibility::AccessibleRole::WINDOW:
388 return "WINDOW";
390 return unknownName(role);
393 OUString AccessibilityTools::debugAccessibleStateSet(const sal_Int64 nCombinedState)
395 OUString combinedName;
397 for (int i = 0; i < 63; i++)
399 sal_Int64 state = sal_Int64(1) << i;
400 if (!(state & nCombinedState))
401 continue;
402 OUString name;
403 switch (state)
405 case accessibility::AccessibleStateType::ACTIVE:
406 name = "ACTIVE";
407 break;
408 case accessibility::AccessibleStateType::ARMED:
409 name = "ARMED";
410 break;
411 case accessibility::AccessibleStateType::BUSY:
412 name = "BUSY";
413 break;
414 case accessibility::AccessibleStateType::CHECKED:
415 name = "CHECKED";
416 break;
417 case accessibility::AccessibleStateType::COLLAPSE:
418 name = "COLLAPSE";
419 break;
420 case accessibility::AccessibleStateType::DEFAULT:
421 name = "DEFAULT";
422 break;
423 case accessibility::AccessibleStateType::DEFUNC:
424 name = "DEFUNC";
425 break;
426 case accessibility::AccessibleStateType::EDITABLE:
427 name = "EDITABLE";
428 break;
429 case accessibility::AccessibleStateType::ENABLED:
430 name = "ENABLED";
431 break;
432 case accessibility::AccessibleStateType::EXPANDABLE:
433 name = "EXPANDABLE";
434 break;
435 case accessibility::AccessibleStateType::EXPANDED:
436 name = "EXPANDED";
437 break;
438 case accessibility::AccessibleStateType::FOCUSABLE:
439 name = "FOCUSABLE";
440 break;
441 case accessibility::AccessibleStateType::FOCUSED:
442 name = "FOCUSED";
443 break;
444 case accessibility::AccessibleStateType::HORIZONTAL:
445 name = "HORIZONTAL";
446 break;
447 case accessibility::AccessibleStateType::ICONIFIED:
448 name = "ICONIFIED";
449 break;
450 case accessibility::AccessibleStateType::INDETERMINATE:
451 name = "INDETERMINATE";
452 break;
453 case accessibility::AccessibleStateType::INVALID:
454 name = "INVALID";
455 break;
456 case accessibility::AccessibleStateType::MANAGES_DESCENDANTS:
457 name = "MANAGES_DESCENDANTS";
458 break;
459 case accessibility::AccessibleStateType::MODAL:
460 name = "MODAL";
461 break;
462 case accessibility::AccessibleStateType::MOVEABLE:
463 name = "MOVEABLE";
464 break;
465 case accessibility::AccessibleStateType::MULTI_LINE:
466 name = "MULTI_LINE";
467 break;
468 case accessibility::AccessibleStateType::MULTI_SELECTABLE:
469 name = "MULTI_SELECTABLE";
470 break;
471 case accessibility::AccessibleStateType::OFFSCREEN:
472 name = "OFFSCREEN";
473 break;
474 case accessibility::AccessibleStateType::OPAQUE:
475 name = "OPAQUE";
476 break;
477 case accessibility::AccessibleStateType::PRESSED:
478 name = "PRESSED";
479 break;
480 case accessibility::AccessibleStateType::RESIZABLE:
481 name = "RESIZABLE";
482 break;
483 case accessibility::AccessibleStateType::SELECTABLE:
484 name = "SELECTABLE";
485 break;
486 case accessibility::AccessibleStateType::SELECTED:
487 name = "SELECTED";
488 break;
489 case accessibility::AccessibleStateType::SENSITIVE:
490 name = "SENSITIVE";
491 break;
492 case accessibility::AccessibleStateType::SHOWING:
493 name = "SHOWING";
494 break;
495 case accessibility::AccessibleStateType::SINGLE_LINE:
496 name = "SINGLE_LINE";
497 break;
498 case accessibility::AccessibleStateType::STALE:
499 name = "STALE";
500 break;
501 case accessibility::AccessibleStateType::TRANSIENT:
502 name = "TRANSIENT";
503 break;
504 case accessibility::AccessibleStateType::VERTICAL:
505 name = "VERTICAL";
506 break;
507 case accessibility::AccessibleStateType::VISIBLE:
508 name = "VISIBLE";
509 break;
510 default:
511 name = unknownName(state);
512 break;
514 if (combinedName.getLength())
515 combinedName += " | ";
516 combinedName += name;
519 if (combinedName.isEmpty())
520 return "unknown";
521 return combinedName;
524 OUString AccessibilityTools::getEventIdName(const sal_Int16 event_id)
526 switch (event_id)
528 case accessibility::AccessibleEventId::ACTION_CHANGED:
529 return "ACTION_CHANGED";
530 case accessibility::AccessibleEventId::ACTIVE_DESCENDANT_CHANGED:
531 return "ACTIVE_DESCENDANT_CHANGED";
532 case accessibility::AccessibleEventId::ACTIVE_DESCENDANT_CHANGED_NOFOCUS:
533 return "ACTIVE_DESCENDANT_CHANGED_NOFOCUS";
534 case accessibility::AccessibleEventId::BOUNDRECT_CHANGED:
535 return "BOUNDRECT_CHANGED";
536 case accessibility::AccessibleEventId::CARET_CHANGED:
537 return "CARET_CHANGED";
538 case accessibility::AccessibleEventId::CHILD:
539 return "CHILD";
540 case accessibility::AccessibleEventId::COLUMN_CHANGED:
541 return "COLUMN_CHANGED";
542 case accessibility::AccessibleEventId::CONTENT_FLOWS_FROM_RELATION_CHANGED:
543 return "CONTENT_FLOWS_FROM_RELATION_CHANGED";
544 case accessibility::AccessibleEventId::CONTENT_FLOWS_TO_RELATION_CHANGED:
545 return "CONTENT_FLOWS_TO_RELATION_CHANGED";
546 case accessibility::AccessibleEventId::CONTROLLED_BY_RELATION_CHANGED:
547 return "CONTROLLED_BY_RELATION_CHANGED";
548 case accessibility::AccessibleEventId::CONTROLLER_FOR_RELATION_CHANGED:
549 return "CONTROLLER_FOR_RELATION_CHANGED";
550 case accessibility::AccessibleEventId::DESCRIPTION_CHANGED:
551 return "DESCRIPTION_CHANGED";
552 case accessibility::AccessibleEventId::HYPERTEXT_CHANGED:
553 return "HYPERTEXT_CHANGED";
554 case accessibility::AccessibleEventId::INVALIDATE_ALL_CHILDREN:
555 return "INVALIDATE_ALL_CHILDREN";
556 case accessibility::AccessibleEventId::LABELED_BY_RELATION_CHANGED:
557 return "LABELED_BY_RELATION_CHANGED";
558 case accessibility::AccessibleEventId::LABEL_FOR_RELATION_CHANGED:
559 return "LABEL_FOR_RELATION_CHANGED";
560 case accessibility::AccessibleEventId::LISTBOX_ENTRY_COLLAPSED:
561 return "LISTBOX_ENTRY_COLLAPSED";
562 case accessibility::AccessibleEventId::LISTBOX_ENTRY_EXPANDED:
563 return "LISTBOX_ENTRY_EXPANDED";
564 case accessibility::AccessibleEventId::MEMBER_OF_RELATION_CHANGED:
565 return "MEMBER_OF_RELATION_CHANGED";
566 case accessibility::AccessibleEventId::NAME_CHANGED:
567 return "NAME_CHANGED";
568 case accessibility::AccessibleEventId::PAGE_CHANGED:
569 return "PAGE_CHANGED";
570 case accessibility::AccessibleEventId::ROLE_CHANGED:
571 return "ROLE_CHANGED";
572 case accessibility::AccessibleEventId::SECTION_CHANGED:
573 return "SECTION_CHANGED";
574 case accessibility::AccessibleEventId::SELECTION_CHANGED:
575 return "SELECTION_CHANGED";
576 case accessibility::AccessibleEventId::SELECTION_CHANGED_ADD:
577 return "SELECTION_CHANGED_ADD";
578 case accessibility::AccessibleEventId::SELECTION_CHANGED_REMOVE:
579 return "SELECTION_CHANGED_REMOVE";
580 case accessibility::AccessibleEventId::SELECTION_CHANGED_WITHIN:
581 return "SELECTION_CHANGED_WITHIN";
582 case accessibility::AccessibleEventId::STATE_CHANGED:
583 return "STATE_CHANGED";
584 case accessibility::AccessibleEventId::SUB_WINDOW_OF_RELATION_CHANGED:
585 return "SUB_WINDOW_OF_RELATION_CHANGED";
586 case accessibility::AccessibleEventId::TABLE_CAPTION_CHANGED:
587 return "TABLE_CAPTION_CHANGED";
588 case accessibility::AccessibleEventId::TABLE_COLUMN_DESCRIPTION_CHANGED:
589 return "TABLE_COLUMN_DESCRIPTION_CHANGED";
590 case accessibility::AccessibleEventId::TABLE_COLUMN_HEADER_CHANGED:
591 return "TABLE_COLUMN_HEADER_CHANGED";
592 case accessibility::AccessibleEventId::TABLE_MODEL_CHANGED:
593 return "TABLE_MODEL_CHANGED";
594 case accessibility::AccessibleEventId::TABLE_ROW_DESCRIPTION_CHANGED:
595 return "TABLE_ROW_DESCRIPTION_CHANGED";
596 case accessibility::AccessibleEventId::TABLE_ROW_HEADER_CHANGED:
597 return "TABLE_ROW_HEADER_CHANGED";
598 case accessibility::AccessibleEventId::TABLE_SUMMARY_CHANGED:
599 return "TABLE_SUMMARY_CHANGED";
600 case accessibility::AccessibleEventId::TEXT_ATTRIBUTE_CHANGED:
601 return "TEXT_ATTRIBUTE_CHANGED";
602 case accessibility::AccessibleEventId::TEXT_CHANGED:
603 return "TEXT_CHANGED";
604 case accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED:
605 return "TEXT_SELECTION_CHANGED";
606 case accessibility::AccessibleEventId::VALUE_CHANGED:
607 return "VALUE_CHANGED";
608 case accessibility::AccessibleEventId::VISIBLE_DATA_CHANGED:
609 return "VISIBLE_DATA_CHANGED";
611 return unknownName(event_id);
614 OUString AccessibilityTools::getRelationTypeName(const sal_Int16 rel_type)
616 switch (rel_type)
618 case accessibility::AccessibleRelationType::CONTENT_FLOWS_FROM:
619 return "CONTENT_FLOWS_FROM";
620 case accessibility::AccessibleRelationType::CONTENT_FLOWS_TO:
621 return "CONTENT_FLOWS_TO";
622 case accessibility::AccessibleRelationType::CONTROLLED_BY:
623 return "CONTROLLED_BY";
624 case accessibility::AccessibleRelationType::CONTROLLER_FOR:
625 return "CONTROLLER_FOR";
626 case accessibility::AccessibleRelationType::DESCRIBED_BY:
627 return "DESCRIBED_BY";
628 case accessibility::AccessibleRelationType::INVALID:
629 return "INVALID";
630 case accessibility::AccessibleRelationType::LABELED_BY:
631 return "LABELED_BY";
632 case accessibility::AccessibleRelationType::LABEL_FOR:
633 return "LABEL_FOR";
634 case accessibility::AccessibleRelationType::MEMBER_OF:
635 return "MEMBER_OF";
636 case accessibility::AccessibleRelationType::NODE_CHILD_OF:
637 return "NODE_CHILD_OF";
638 case accessibility::AccessibleRelationType::SUB_WINDOW_OF:
639 return "SUB_WINDOW_OF";
641 return unknownName(rel_type);
644 OUString AccessibilityTools::debugName(accessibility::XAccessibleContext* ctx)
646 return "role=" + AccessibilityTools::getRoleName(ctx->getAccessibleRole()) + " name=\""
647 + ctx->getAccessibleName() + "\" description=\"" + ctx->getAccessibleDescription()
648 + "\"";
651 OUString AccessibilityTools::debugName(accessibility::XAccessible* acc)
653 return debugName(acc->getAccessibleContext().get());
656 OUString AccessibilityTools::debugName(accessibility::XAccessibleAction* xAct)
658 OUStringBuffer r = "actions=[";
660 const sal_Int32 nActions = xAct->getAccessibleActionCount();
661 for (sal_Int32 i = 0; i < nActions; i++)
663 if (i > 0)
664 r.append(", ");
666 r.append("description=\"" + xAct->getAccessibleActionDescription(i) + "\"");
668 const auto& xKeyBinding = xAct->getAccessibleActionKeyBinding(i);
669 if (xKeyBinding)
671 r.append(" keybindings=[");
672 const sal_Int32 nKeyBindings = xKeyBinding->getAccessibleKeyBindingCount();
673 for (sal_Int32 j = 0; j < nKeyBindings; j++)
675 if (j > 0)
676 r.append(", ");
678 int k = 0;
679 for (const auto& keyStroke : xKeyBinding->getAccessibleKeyBinding(j))
681 if (k++ > 0)
682 r.append(", ");
684 r.append('"');
685 if (keyStroke.Modifiers & awt::KeyModifier::MOD1)
686 r.append("<Mod1>");
687 if (keyStroke.Modifiers & awt::KeyModifier::MOD2)
688 r.append("<Mod2>");
689 if (keyStroke.Modifiers & awt::KeyModifier::MOD3)
690 r.append("<Mod3>");
691 if (keyStroke.Modifiers & awt::KeyModifier::SHIFT)
692 r.append("<Shift>");
693 r.append(OUStringChar(keyStroke.KeyChar) + "\"");
696 r.append("]");
699 r.append("]");
700 return r.makeStringAndClear();
703 OUString AccessibilityTools::debugName(const accessibility::AccessibleEventObject* evobj)
705 return "(AccessibleEventObject) { id=" + getEventIdName(evobj->EventId)
706 + " old=" + evobj->OldValue.getValueTypeName()
707 + " new=" + evobj->NewValue.getValueTypeName() + " }";
710 bool AccessibilityTools::Await(const std::function<bool()>& cUntilCallback, sal_uInt64 nTimeoutMs)
712 bool success = false;
713 Timer aTimer("wait for event");
714 aTimer.SetTimeout(nTimeoutMs);
715 aTimer.Start();
718 Scheduler::ProcessEventsToIdle();
719 success = cUntilCallback();
720 } while (!success && aTimer.IsActive());
721 SAL_WARN_IF(!success, "test", "timeout reached");
722 return success;
725 void AccessibilityTools::Wait(sal_uInt64 nTimeoutMs)
727 Timer aTimer("wait for event");
728 aTimer.SetTimeout(nTimeoutMs);
729 aTimer.Start();
730 std::cout << "waiting for " << nTimeoutMs << "ms... ";
733 Scheduler::ProcessEventsToIdle();
734 } while (aTimer.IsActive());
735 std::cout << "ok." << std::endl;
738 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */