tdf#161411 - UI: Add Better wording for ASCII-only characters
[LibreOffice.git] / test / source / a11y / AccessibilityTools.cxx
blob2003e6871d012432030d2142f5a0ba0b02e3312b
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 <vcl/accessibility/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::getAccessibleObjectForId(
74 const uno::Reference<accessibility::XAccessibleContext>& xCtx, std::u16string_view sId)
76 return getAccessibleObjectForPredicate(
77 xCtx, [&](const uno::Reference<accessibility::XAccessibleContext>& xObjCtx) {
78 uno::Reference<accessibility::XAccessibleContext2> xContext2(xObjCtx, uno::UNO_QUERY);
79 return (xContext2 && xContext2->getAccessibleId() == sId);
80 });
83 css::uno::Reference<css::accessibility::XAccessibleContext>
84 AccessibilityTools::getAccessibleObjectForId(
85 const css::uno::Reference<css::accessibility::XAccessible>& xacc, const std::u16string_view sId)
87 return getAccessibleObjectForId(xacc->getAccessibleContext(), sId);
90 uno::Reference<accessibility::XAccessibleContext> AccessibilityTools::getAccessibleObjectForRole(
91 const uno::Reference<accessibility::XAccessibleContext>& xCtx, sal_Int16 role)
93 return getAccessibleObjectForPredicate(
94 xCtx, [&role](const uno::Reference<accessibility::XAccessibleContext>& xObjCtx) {
95 return (xObjCtx->getAccessibleRole() == role
96 && xObjCtx->getAccessibleStateSet()
97 & accessibility::AccessibleStateType::SHOWING);
98 });
101 css::uno::Reference<css::accessibility::XAccessibleContext>
102 AccessibilityTools::getAccessibleObjectForRole(
103 const css::uno::Reference<css::accessibility::XAccessible>& xacc, sal_Int16 role)
105 return getAccessibleObjectForRole(xacc->getAccessibleContext(), role);
108 /* this is basically the same as getAccessibleObjectForPredicate() but specialized for efficiency,
109 * and because the template version will not work with getAccessibleObjectForPredicate() anyway */
110 css::uno::Reference<css::accessibility::XAccessibleContext>
111 AccessibilityTools::getAccessibleObjectForName(
112 const css::uno::Reference<css::accessibility::XAccessibleContext>& xCtx, const sal_Int16 role,
113 std::u16string_view name)
115 if (xCtx->getAccessibleRole() == role && nameEquals(xCtx, name))
116 return xCtx;
118 auto nChildren = xCtx->getAccessibleChildCount();
119 for (decltype(nChildren) i = 0; i < nChildren && i < AccessibilityTools::MAX_CHILDREN; i++)
121 if (auto xMatchChild = getAccessibleObjectForName(xCtx->getAccessibleChild(i), role, name))
122 return xMatchChild;
125 return nullptr;
128 bool AccessibilityTools::equals(const uno::Reference<accessibility::XAccessible>& xacc1,
129 const uno::Reference<accessibility::XAccessible>& xacc2)
131 if (!xacc1.is() || !xacc2.is())
132 return xacc1.is() == xacc2.is();
133 return equals(xacc1->getAccessibleContext(), xacc2->getAccessibleContext());
136 bool AccessibilityTools::equals(const uno::Reference<accessibility::XAccessibleContext>& xctx1,
137 const uno::Reference<accessibility::XAccessibleContext>& xctx2)
139 if (!xctx1.is() || !xctx2.is())
140 return xctx1.is() == xctx2.is();
142 if (xctx1->getAccessibleRole() != xctx2->getAccessibleRole())
143 return false;
145 if (xctx1->getAccessibleName() != xctx2->getAccessibleName())
146 return false;
148 if (xctx1->getAccessibleDescription() != xctx2->getAccessibleDescription())
149 return false;
151 if (xctx1->getAccessibleChildCount() != xctx2->getAccessibleChildCount())
152 return false;
154 /* this one was not in the Java version */
155 if (xctx1->getAccessibleIndexInParent() != xctx2->getAccessibleIndexInParent())
156 return false;
158 /* because in Writer at least some children only are referenced by their relations to others
159 * objects, we need to account for that as their index in parent is incorrect (so not
160 * necessarily unique) */
161 auto relset1 = xctx1->getAccessibleRelationSet();
162 auto relset2 = xctx2->getAccessibleRelationSet();
163 if (relset1.is() != relset2.is())
164 return false;
165 else if (relset1.is())
167 auto relCount1 = relset1->getRelationCount();
168 auto relCount2 = relset2->getRelationCount();
169 if (relCount1 != relCount2)
170 return false;
172 for (sal_Int32 i = 0; i < relCount1; ++i)
174 if (relset1->getRelation(i) != relset2->getRelation(i))
175 return false;
179 return equals(xctx1->getAccessibleParent(), xctx2->getAccessibleParent());
182 bool AccessibilityTools::nameEquals(const uno::Reference<accessibility::XAccessibleContext>& xCtx,
183 const std::u16string_view name)
185 auto ctxName = xCtx->getAccessibleName();
186 std::u16string_view rest;
188 if (!o3tl::starts_with(ctxName, name, &rest))
189 return false;
190 if (rest == u"")
191 return true;
193 #if defined(_WIN32)
194 // see OAccessibleMenuItemComponent::GetAccessibleName():
195 // on Win32, ignore a \tSHORTCUT suffix on a menu item
196 switch (xCtx->getAccessibleRole())
198 case accessibility::AccessibleRole::MENU_ITEM:
199 case accessibility::AccessibleRole::RADIO_MENU_ITEM:
200 case accessibility::AccessibleRole::CHECK_MENU_ITEM:
201 return rest[0] == '\t';
203 default:
204 break;
206 #endif
208 #if OSL_DEBUG_LEVEL > 0
209 // see VCLXAccessibleComponent::getAccessibleName()
210 static const char* pEnvAppendType = getenv("LIBO_APPEND_WINDOW_TYPE_TO_ACCESSIBLE_NAME");
211 if (pEnvAppendType && OUString::createFromAscii(pEnvAppendType) != u"0")
213 auto pVCLXAccessibleComponent = dynamic_cast<VCLXAccessibleComponent*>(xCtx.get());
214 if (pVCLXAccessibleComponent)
216 auto windowType = pVCLXAccessibleComponent->GetWindow()->GetType();
217 if (rest
218 == Concat2View(u" (Type = " + OUString::number(static_cast<sal_Int32>(windowType))
219 + ")"))
220 return true;
223 #endif
224 return false;
227 static OUString unknownName(const sal_Int64 value)
229 return "unknown (" + OUString::number(value) + ")";
232 OUString AccessibilityTools::getRoleName(const sal_Int16 role)
234 switch (role)
236 case accessibility::AccessibleRole::UNKNOWN:
237 return u"UNKNOWN"_ustr;
238 case accessibility::AccessibleRole::ALERT:
239 return u"ALERT"_ustr;
240 case accessibility::AccessibleRole::BLOCK_QUOTE:
241 return u"BLOCK_QUOTE"_ustr;
242 case accessibility::AccessibleRole::BUTTON_DROPDOWN:
243 return u"BUTTON_DROPDOWN"_ustr;
244 case accessibility::AccessibleRole::BUTTON_MENU:
245 return u"BUTTON_MENU"_ustr;
246 case accessibility::AccessibleRole::CANVAS:
247 return u"CANVAS"_ustr;
248 case accessibility::AccessibleRole::CAPTION:
249 return u"CAPTION"_ustr;
250 case accessibility::AccessibleRole::CHART:
251 return u"CHART"_ustr;
252 case accessibility::AccessibleRole::CHECK_BOX:
253 return u"CHECK_BOX"_ustr;
254 case accessibility::AccessibleRole::CHECK_MENU_ITEM:
255 return u"CHECK_MENU_ITEM"_ustr;
256 case accessibility::AccessibleRole::COLOR_CHOOSER:
257 return u"COLOR_CHOOSER"_ustr;
258 case accessibility::AccessibleRole::COLUMN_HEADER:
259 return u"COLUMN_HEADER"_ustr;
260 case accessibility::AccessibleRole::COMBO_BOX:
261 return u"COMBO_BOX"_ustr;
262 case accessibility::AccessibleRole::COMMENT:
263 return u"COMMENT"_ustr;
264 case accessibility::AccessibleRole::COMMENT_END:
265 return u"COMMENT_END"_ustr;
266 case accessibility::AccessibleRole::DATE_EDITOR:
267 return u"DATE_EDITOR"_ustr;
268 case accessibility::AccessibleRole::DESKTOP_ICON:
269 return u"DESKTOP_ICON"_ustr;
270 case accessibility::AccessibleRole::DESKTOP_PANE:
271 return u"DESKTOP_PANE"_ustr;
272 case accessibility::AccessibleRole::DIALOG:
273 return u"DIALOG"_ustr;
274 case accessibility::AccessibleRole::DIRECTORY_PANE:
275 return u"DIRECTORY_PANE"_ustr;
276 case accessibility::AccessibleRole::DOCUMENT:
277 return u"DOCUMENT"_ustr;
278 case accessibility::AccessibleRole::DOCUMENT_PRESENTATION:
279 return u"DOCUMENT_PRESENTATION"_ustr;
280 case accessibility::AccessibleRole::DOCUMENT_SPREADSHEET:
281 return u"DOCUMENT_SPREADSHEET"_ustr;
282 case accessibility::AccessibleRole::DOCUMENT_TEXT:
283 return u"DOCUMENT_TEXT"_ustr;
284 case accessibility::AccessibleRole::EDIT_BAR:
285 return u"EDIT_BAR"_ustr;
286 case accessibility::AccessibleRole::EMBEDDED_OBJECT:
287 return u"EMBEDDED_OBJECT"_ustr;
288 case accessibility::AccessibleRole::END_NOTE:
289 return u"END_NOTE"_ustr;
290 case accessibility::AccessibleRole::FILE_CHOOSER:
291 return u"FILE_CHOOSER"_ustr;
292 case accessibility::AccessibleRole::FILLER:
293 return u"FILLER"_ustr;
294 case accessibility::AccessibleRole::FONT_CHOOSER:
295 return u"FONT_CHOOSER"_ustr;
296 case accessibility::AccessibleRole::FOOTER:
297 return u"FOOTER"_ustr;
298 case accessibility::AccessibleRole::FOOTNOTE:
299 return u"FOOTNOTE"_ustr;
300 case accessibility::AccessibleRole::FORM:
301 return u"FORM"_ustr;
302 case accessibility::AccessibleRole::FRAME:
303 return u"FRAME"_ustr;
304 case accessibility::AccessibleRole::GLASS_PANE:
305 return u"GLASS_PANE"_ustr;
306 case accessibility::AccessibleRole::GRAPHIC:
307 return u"GRAPHIC"_ustr;
308 case accessibility::AccessibleRole::GROUP_BOX:
309 return u"GROUP_BOX"_ustr;
310 case accessibility::AccessibleRole::HEADER:
311 return u"HEADER"_ustr;
312 case accessibility::AccessibleRole::HEADING:
313 return u"HEADING"_ustr;
314 case accessibility::AccessibleRole::HYPER_LINK:
315 return u"HYPER_LINK"_ustr;
316 case accessibility::AccessibleRole::ICON:
317 return u"ICON"_ustr;
318 case accessibility::AccessibleRole::IMAGE_MAP:
319 return u"IMAGE_MAP"_ustr;
320 case accessibility::AccessibleRole::INTERNAL_FRAME:
321 return u"INTERNAL_FRAME"_ustr;
322 case accessibility::AccessibleRole::LABEL:
323 return u"LABEL"_ustr;
324 case accessibility::AccessibleRole::LAYERED_PANE:
325 return u"LAYERED_PANE"_ustr;
326 case accessibility::AccessibleRole::LIST:
327 return u"LIST"_ustr;
328 case accessibility::AccessibleRole::LIST_ITEM:
329 return u"LIST_ITEM"_ustr;
330 case accessibility::AccessibleRole::MENU:
331 return u"MENU"_ustr;
332 case accessibility::AccessibleRole::MENU_BAR:
333 return u"MENU_BAR"_ustr;
334 case accessibility::AccessibleRole::MENU_ITEM:
335 return u"MENU_ITEM"_ustr;
336 case accessibility::AccessibleRole::NOTE:
337 return u"NOTE"_ustr;
338 case accessibility::AccessibleRole::OPTION_PANE:
339 return u"OPTION_PANE"_ustr;
340 case accessibility::AccessibleRole::PAGE:
341 return u"PAGE"_ustr;
342 case accessibility::AccessibleRole::PAGE_TAB:
343 return u"PAGE_TAB"_ustr;
344 case accessibility::AccessibleRole::PAGE_TAB_LIST:
345 return u"PAGE_TAB_LIST"_ustr;
346 case accessibility::AccessibleRole::PANEL:
347 return u"PANEL"_ustr;
348 case accessibility::AccessibleRole::PARAGRAPH:
349 return u"PARAGRAPH"_ustr;
350 case accessibility::AccessibleRole::PASSWORD_TEXT:
351 return u"PASSWORD_TEXT"_ustr;
352 case accessibility::AccessibleRole::POPUP_MENU:
353 return u"POPUP_MENU"_ustr;
354 case accessibility::AccessibleRole::PROGRESS_BAR:
355 return u"PROGRESS_BAR"_ustr;
356 case accessibility::AccessibleRole::PUSH_BUTTON:
357 return u"PUSH_BUTTON"_ustr;
358 case accessibility::AccessibleRole::RADIO_BUTTON:
359 return u"RADIO_BUTTON"_ustr;
360 case accessibility::AccessibleRole::RADIO_MENU_ITEM:
361 return u"RADIO_MENU_ITEM"_ustr;
362 case accessibility::AccessibleRole::ROOT_PANE:
363 return u"ROOT_PANE"_ustr;
364 case accessibility::AccessibleRole::ROW_HEADER:
365 return u"ROW_HEADER"_ustr;
366 case accessibility::AccessibleRole::RULER:
367 return u"RULER"_ustr;
368 case accessibility::AccessibleRole::SCROLL_BAR:
369 return u"SCROLL_BAR"_ustr;
370 case accessibility::AccessibleRole::SCROLL_PANE:
371 return u"SCROLL_PANE"_ustr;
372 case accessibility::AccessibleRole::SECTION:
373 return u"SECTION"_ustr;
374 case accessibility::AccessibleRole::SEPARATOR:
375 return u"SEPARATOR"_ustr;
376 case accessibility::AccessibleRole::SHAPE:
377 return u"SHAPE"_ustr;
378 case accessibility::AccessibleRole::SLIDER:
379 return u"SLIDER"_ustr;
380 case accessibility::AccessibleRole::SPIN_BOX:
381 return u"SPIN_BOX"_ustr;
382 case accessibility::AccessibleRole::SPLIT_PANE:
383 return u"SPLIT_PANE"_ustr;
384 case accessibility::AccessibleRole::STATIC:
385 return u"STATIC"_ustr;
386 case accessibility::AccessibleRole::STATUS_BAR:
387 return u"STATUS_BAR"_ustr;
388 case accessibility::AccessibleRole::TABLE:
389 return u"TABLE"_ustr;
390 case accessibility::AccessibleRole::TABLE_CELL:
391 return u"TABLE_CELL"_ustr;
392 case accessibility::AccessibleRole::TEXT:
393 return u"TEXT"_ustr;
394 case accessibility::AccessibleRole::TEXT_FRAME:
395 return u"TEXT_FRAME"_ustr;
396 case accessibility::AccessibleRole::TOGGLE_BUTTON:
397 return u"TOGGLE_BUTTON"_ustr;
398 case accessibility::AccessibleRole::TOOL_BAR:
399 return u"TOOL_BAR"_ustr;
400 case accessibility::AccessibleRole::TOOL_TIP:
401 return u"TOOL_TIP"_ustr;
402 case accessibility::AccessibleRole::TREE:
403 return u"TREE"_ustr;
404 case accessibility::AccessibleRole::TREE_ITEM:
405 return u"TREE_ITEM"_ustr;
406 case accessibility::AccessibleRole::TREE_TABLE:
407 return u"TREE_TABLE"_ustr;
408 case accessibility::AccessibleRole::VIEW_PORT:
409 return u"VIEW_PORT"_ustr;
410 case accessibility::AccessibleRole::WINDOW:
411 return u"WINDOW"_ustr;
413 return unknownName(role);
416 OUString AccessibilityTools::debugAccessibleStateSet(const sal_Int64 nCombinedState)
418 OUString combinedName;
420 for (int i = 0; i < 63; i++)
422 sal_Int64 state = sal_Int64(1) << i;
423 if (!(state & nCombinedState))
424 continue;
425 OUString name;
426 switch (state)
428 case accessibility::AccessibleStateType::ACTIVE:
429 name = "ACTIVE";
430 break;
431 case accessibility::AccessibleStateType::ARMED:
432 name = "ARMED";
433 break;
434 case accessibility::AccessibleStateType::BUSY:
435 name = "BUSY";
436 break;
437 case accessibility::AccessibleStateType::CHECKABLE:
438 name = "CHECKABLE";
439 break;
440 case accessibility::AccessibleStateType::CHECKED:
441 name = "CHECKED";
442 break;
443 case accessibility::AccessibleStateType::COLLAPSE:
444 name = "COLLAPSE";
445 break;
446 case accessibility::AccessibleStateType::DEFAULT:
447 name = "DEFAULT";
448 break;
449 case accessibility::AccessibleStateType::DEFUNC:
450 name = "DEFUNC";
451 break;
452 case accessibility::AccessibleStateType::EDITABLE:
453 name = "EDITABLE";
454 break;
455 case accessibility::AccessibleStateType::ENABLED:
456 name = "ENABLED";
457 break;
458 case accessibility::AccessibleStateType::EXPANDABLE:
459 name = "EXPANDABLE";
460 break;
461 case accessibility::AccessibleStateType::EXPANDED:
462 name = "EXPANDED";
463 break;
464 case accessibility::AccessibleStateType::FOCUSABLE:
465 name = "FOCUSABLE";
466 break;
467 case accessibility::AccessibleStateType::FOCUSED:
468 name = "FOCUSED";
469 break;
470 case accessibility::AccessibleStateType::HORIZONTAL:
471 name = "HORIZONTAL";
472 break;
473 case accessibility::AccessibleStateType::ICONIFIED:
474 name = "ICONIFIED";
475 break;
476 case accessibility::AccessibleStateType::INDETERMINATE:
477 name = "INDETERMINATE";
478 break;
479 case accessibility::AccessibleStateType::INVALID:
480 name = "INVALID";
481 break;
482 case accessibility::AccessibleStateType::MANAGES_DESCENDANTS:
483 name = "MANAGES_DESCENDANTS";
484 break;
485 case accessibility::AccessibleStateType::MODAL:
486 name = "MODAL";
487 break;
488 case accessibility::AccessibleStateType::MOVEABLE:
489 name = "MOVEABLE";
490 break;
491 case accessibility::AccessibleStateType::MULTI_LINE:
492 name = "MULTI_LINE";
493 break;
494 case accessibility::AccessibleStateType::MULTI_SELECTABLE:
495 name = "MULTI_SELECTABLE";
496 break;
497 case accessibility::AccessibleStateType::OFFSCREEN:
498 name = "OFFSCREEN";
499 break;
500 case accessibility::AccessibleStateType::OPAQUE:
501 name = "OPAQUE";
502 break;
503 case accessibility::AccessibleStateType::PRESSED:
504 name = "PRESSED";
505 break;
506 case accessibility::AccessibleStateType::RESIZABLE:
507 name = "RESIZABLE";
508 break;
509 case accessibility::AccessibleStateType::SELECTABLE:
510 name = "SELECTABLE";
511 break;
512 case accessibility::AccessibleStateType::SELECTED:
513 name = "SELECTED";
514 break;
515 case accessibility::AccessibleStateType::SENSITIVE:
516 name = "SENSITIVE";
517 break;
518 case accessibility::AccessibleStateType::SHOWING:
519 name = "SHOWING";
520 break;
521 case accessibility::AccessibleStateType::SINGLE_LINE:
522 name = "SINGLE_LINE";
523 break;
524 case accessibility::AccessibleStateType::STALE:
525 name = "STALE";
526 break;
527 case accessibility::AccessibleStateType::TRANSIENT:
528 name = "TRANSIENT";
529 break;
530 case accessibility::AccessibleStateType::VERTICAL:
531 name = "VERTICAL";
532 break;
533 case accessibility::AccessibleStateType::VISIBLE:
534 name = "VISIBLE";
535 break;
536 default:
537 name = unknownName(state);
538 break;
540 if (combinedName.getLength())
541 combinedName += " | ";
542 combinedName += name;
545 if (combinedName.isEmpty())
546 return u"unknown"_ustr;
547 return combinedName;
550 OUString AccessibilityTools::getEventIdName(const sal_Int16 event_id)
552 switch (event_id)
554 case accessibility::AccessibleEventId::ACTION_CHANGED:
555 return u"ACTION_CHANGED"_ustr;
556 case accessibility::AccessibleEventId::ACTIVE_DESCENDANT_CHANGED:
557 return u"ACTIVE_DESCENDANT_CHANGED"_ustr;
558 case accessibility::AccessibleEventId::ACTIVE_DESCENDANT_CHANGED_NOFOCUS:
559 return u"ACTIVE_DESCENDANT_CHANGED_NOFOCUS"_ustr;
560 case accessibility::AccessibleEventId::BOUNDRECT_CHANGED:
561 return u"BOUNDRECT_CHANGED"_ustr;
562 case accessibility::AccessibleEventId::CARET_CHANGED:
563 return u"CARET_CHANGED"_ustr;
564 case accessibility::AccessibleEventId::CHILD:
565 return u"CHILD"_ustr;
566 case accessibility::AccessibleEventId::COLUMN_CHANGED:
567 return u"COLUMN_CHANGED"_ustr;
568 case accessibility::AccessibleEventId::CONTENT_FLOWS_FROM_RELATION_CHANGED:
569 return u"CONTENT_FLOWS_FROM_RELATION_CHANGED"_ustr;
570 case accessibility::AccessibleEventId::CONTENT_FLOWS_TO_RELATION_CHANGED:
571 return u"CONTENT_FLOWS_TO_RELATION_CHANGED"_ustr;
572 case accessibility::AccessibleEventId::CONTROLLED_BY_RELATION_CHANGED:
573 return u"CONTROLLED_BY_RELATION_CHANGED"_ustr;
574 case accessibility::AccessibleEventId::CONTROLLER_FOR_RELATION_CHANGED:
575 return u"CONTROLLER_FOR_RELATION_CHANGED"_ustr;
576 case accessibility::AccessibleEventId::DESCRIPTION_CHANGED:
577 return u"DESCRIPTION_CHANGED"_ustr;
578 case accessibility::AccessibleEventId::HYPERTEXT_CHANGED:
579 return u"HYPERTEXT_CHANGED"_ustr;
580 case accessibility::AccessibleEventId::INVALIDATE_ALL_CHILDREN:
581 return u"INVALIDATE_ALL_CHILDREN"_ustr;
582 case accessibility::AccessibleEventId::LABELED_BY_RELATION_CHANGED:
583 return u"LABELED_BY_RELATION_CHANGED"_ustr;
584 case accessibility::AccessibleEventId::LABEL_FOR_RELATION_CHANGED:
585 return u"LABEL_FOR_RELATION_CHANGED"_ustr;
586 case accessibility::AccessibleEventId::LISTBOX_ENTRY_COLLAPSED:
587 return u"LISTBOX_ENTRY_COLLAPSED"_ustr;
588 case accessibility::AccessibleEventId::LISTBOX_ENTRY_EXPANDED:
589 return u"LISTBOX_ENTRY_EXPANDED"_ustr;
590 case accessibility::AccessibleEventId::MEMBER_OF_RELATION_CHANGED:
591 return u"MEMBER_OF_RELATION_CHANGED"_ustr;
592 case accessibility::AccessibleEventId::NAME_CHANGED:
593 return u"NAME_CHANGED"_ustr;
594 case accessibility::AccessibleEventId::PAGE_CHANGED:
595 return u"PAGE_CHANGED"_ustr;
596 case accessibility::AccessibleEventId::ROLE_CHANGED:
597 return u"ROLE_CHANGED"_ustr;
598 case accessibility::AccessibleEventId::SECTION_CHANGED:
599 return u"SECTION_CHANGED"_ustr;
600 case accessibility::AccessibleEventId::SELECTION_CHANGED:
601 return u"SELECTION_CHANGED"_ustr;
602 case accessibility::AccessibleEventId::SELECTION_CHANGED_ADD:
603 return u"SELECTION_CHANGED_ADD"_ustr;
604 case accessibility::AccessibleEventId::SELECTION_CHANGED_REMOVE:
605 return u"SELECTION_CHANGED_REMOVE"_ustr;
606 case accessibility::AccessibleEventId::SELECTION_CHANGED_WITHIN:
607 return u"SELECTION_CHANGED_WITHIN"_ustr;
608 case accessibility::AccessibleEventId::STATE_CHANGED:
609 return u"STATE_CHANGED"_ustr;
610 case accessibility::AccessibleEventId::SUB_WINDOW_OF_RELATION_CHANGED:
611 return u"SUB_WINDOW_OF_RELATION_CHANGED"_ustr;
612 case accessibility::AccessibleEventId::TABLE_CAPTION_CHANGED:
613 return u"TABLE_CAPTION_CHANGED"_ustr;
614 case accessibility::AccessibleEventId::TABLE_COLUMN_DESCRIPTION_CHANGED:
615 return u"TABLE_COLUMN_DESCRIPTION_CHANGED"_ustr;
616 case accessibility::AccessibleEventId::TABLE_COLUMN_HEADER_CHANGED:
617 return u"TABLE_COLUMN_HEADER_CHANGED"_ustr;
618 case accessibility::AccessibleEventId::TABLE_MODEL_CHANGED:
619 return u"TABLE_MODEL_CHANGED"_ustr;
620 case accessibility::AccessibleEventId::TABLE_ROW_DESCRIPTION_CHANGED:
621 return u"TABLE_ROW_DESCRIPTION_CHANGED"_ustr;
622 case accessibility::AccessibleEventId::TABLE_ROW_HEADER_CHANGED:
623 return u"TABLE_ROW_HEADER_CHANGED"_ustr;
624 case accessibility::AccessibleEventId::TABLE_SUMMARY_CHANGED:
625 return u"TABLE_SUMMARY_CHANGED"_ustr;
626 case accessibility::AccessibleEventId::TEXT_ATTRIBUTE_CHANGED:
627 return u"TEXT_ATTRIBUTE_CHANGED"_ustr;
628 case accessibility::AccessibleEventId::TEXT_CHANGED:
629 return u"TEXT_CHANGED"_ustr;
630 case accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED:
631 return u"TEXT_SELECTION_CHANGED"_ustr;
632 case accessibility::AccessibleEventId::VALUE_CHANGED:
633 return u"VALUE_CHANGED"_ustr;
634 case accessibility::AccessibleEventId::VISIBLE_DATA_CHANGED:
635 return u"VISIBLE_DATA_CHANGED"_ustr;
637 return unknownName(event_id);
640 OUString AccessibilityTools::getRelationTypeName(AccessibleRelationType rel_type)
642 switch (rel_type)
644 case accessibility::AccessibleRelationType_CONTENT_FLOWS_FROM:
645 return u"CONTENT_FLOWS_FROM"_ustr;
646 case accessibility::AccessibleRelationType_CONTENT_FLOWS_TO:
647 return u"CONTENT_FLOWS_TO"_ustr;
648 case accessibility::AccessibleRelationType_CONTROLLED_BY:
649 return u"CONTROLLED_BY"_ustr;
650 case accessibility::AccessibleRelationType_CONTROLLER_FOR:
651 return u"CONTROLLER_FOR"_ustr;
652 case accessibility::AccessibleRelationType_DESCRIBED_BY:
653 return u"DESCRIBED_BY"_ustr;
654 case accessibility::AccessibleRelationType_INVALID:
655 return u"INVALID"_ustr;
656 case accessibility::AccessibleRelationType_LABELED_BY:
657 return u"LABELED_BY"_ustr;
658 case accessibility::AccessibleRelationType_LABEL_FOR:
659 return u"LABEL_FOR"_ustr;
660 case accessibility::AccessibleRelationType_MEMBER_OF:
661 return u"MEMBER_OF"_ustr;
662 case accessibility::AccessibleRelationType_NODE_CHILD_OF:
663 return u"NODE_CHILD_OF"_ustr;
664 case accessibility::AccessibleRelationType_SUB_WINDOW_OF:
665 return u"SUB_WINDOW_OF"_ustr;
666 default:
667 return unknownName(static_cast<sal_Int64>(rel_type));
671 OUString AccessibilityTools::debugName(accessibility::XAccessibleContext* ctx)
673 return "role=" + AccessibilityTools::getRoleName(ctx->getAccessibleRole()) + " name=\""
674 + ctx->getAccessibleName() + "\" description=\"" + ctx->getAccessibleDescription()
675 + "\"";
678 OUString AccessibilityTools::debugName(accessibility::XAccessible* acc)
680 return debugName(acc->getAccessibleContext().get());
683 OUString AccessibilityTools::debugName(accessibility::XAccessibleAction* xAct)
685 OUStringBuffer r = "actions=[";
687 const sal_Int32 nActions = xAct->getAccessibleActionCount();
688 for (sal_Int32 i = 0; i < nActions; i++)
690 if (i > 0)
691 r.append(", ");
693 r.append("description=\"" + xAct->getAccessibleActionDescription(i) + "\"");
695 const auto xKeyBinding = xAct->getAccessibleActionKeyBinding(i);
696 if (xKeyBinding)
698 r.append(" keybindings=[");
699 const sal_Int32 nKeyBindings = xKeyBinding->getAccessibleKeyBindingCount();
700 for (sal_Int32 j = 0; j < nKeyBindings; j++)
702 if (j > 0)
703 r.append(", ");
705 int k = 0;
706 for (const auto& keyStroke : xKeyBinding->getAccessibleKeyBinding(j))
708 if (k++ > 0)
709 r.append(", ");
711 r.append('"');
712 if (keyStroke.Modifiers & awt::KeyModifier::MOD1)
713 r.append("<Mod1>");
714 if (keyStroke.Modifiers & awt::KeyModifier::MOD2)
715 r.append("<Mod2>");
716 if (keyStroke.Modifiers & awt::KeyModifier::MOD3)
717 r.append("<Mod3>");
718 if (keyStroke.Modifiers & awt::KeyModifier::SHIFT)
719 r.append("<Shift>");
720 r.append(OUStringChar(keyStroke.KeyChar) + "\"");
723 r.append("]");
726 r.append("]");
727 return r.makeStringAndClear();
730 OUString AccessibilityTools::debugName(accessibility::XAccessibleText* xTxt)
732 uno::Reference<accessibility::XAccessibleContext> xCtx(xTxt, uno::UNO_QUERY);
733 return debugName(xCtx.get());
736 OUString AccessibilityTools::debugName(const accessibility::AccessibleEventObject* evobj)
738 return "(AccessibleEventObject) { id=" + getEventIdName(evobj->EventId)
739 + " old=" + evobj->OldValue.getValueTypeName()
740 + " new=" + evobj->NewValue.getValueTypeName() + " }";
743 bool AccessibilityTools::Await(const std::function<bool()>& cUntilCallback, sal_uInt64 nTimeoutMs)
745 bool success = false;
746 Timer aTimer("wait for event");
747 aTimer.SetTimeout(nTimeoutMs);
748 aTimer.Start();
751 Scheduler::ProcessEventsToIdle();
752 success = cUntilCallback();
753 } while (!success && aTimer.IsActive());
754 SAL_WARN_IF(!success, "test", "timeout reached");
755 return success;
758 void AccessibilityTools::Wait(sal_uInt64 nTimeoutMs)
760 Timer aTimer("wait for event");
761 aTimer.SetTimeout(nTimeoutMs);
762 aTimer.Start();
763 std::cout << "waiting for " << nTimeoutMs << "ms... ";
766 Scheduler::ProcessEventsToIdle();
767 } while (aTimer.IsActive());
768 std::cout << "ok." << std::endl;
771 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */