diff options
Diffstat (limited to 'test/source/a11y/AccessibilityTools.cxx')
-rw-r--r-- | test/source/a11y/AccessibilityTools.cxx | 753 |
1 files changed, 753 insertions, 0 deletions
diff --git a/test/source/a11y/AccessibilityTools.cxx b/test/source/a11y/AccessibilityTools.cxx new file mode 100644 index 0000000000..f0a28d4cda --- /dev/null +++ b/test/source/a11y/AccessibilityTools.cxx @@ -0,0 +1,753 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <test/a11y/AccessibilityTools.hxx> + +#include <com/sun/star/accessibility/AccessibleEventId.hpp> +#include <com/sun/star/accessibility/AccessibleRelationType.hpp> +#include <com/sun/star/accessibility/AccessibleRole.hpp> +#include <com/sun/star/accessibility/AccessibleStateType.hpp> +#include <com/sun/star/accessibility/XAccessible.hpp> +#include <com/sun/star/accessibility/XAccessibleAction.hpp> +#include <com/sun/star/accessibility/XAccessibleContext.hpp> +#include <com/sun/star/awt/KeyModifier.hpp> + +#include <rtl/ustrbuf.hxx> +#include <sal/log.hxx> +#include <toolkit/awt/vclxaccessiblecomponent.hxx> +#include <vcl/scheduler.hxx> +#include <vcl/timer.hxx> +#include <vcl/window.hxx> +#include <o3tl/string_view.hxx> + +using namespace css; + +uno::Reference<accessibility::XAccessibleContext> +AccessibilityTools::getAccessibleObjectForPredicate( + const uno::Reference<accessibility::XAccessibleContext>& xCtx, + const std::function<bool(const uno::Reference<accessibility::XAccessibleContext>&)>& cPredicate) +{ + if (cPredicate(xCtx)) + { + return xCtx; + } + else + { + sal_Int64 count = xCtx->getAccessibleChildCount(); + + for (sal_Int64 i = 0; i < count && i < AccessibilityTools::MAX_CHILDREN; i++) + { + uno::Reference<accessibility::XAccessibleContext> xCtx2 + = getAccessibleObjectForPredicate(xCtx->getAccessibleChild(i), cPredicate); + if (xCtx2.is()) + return xCtx2; + } + } + return nullptr; +} + +uno::Reference<accessibility::XAccessibleContext> +AccessibilityTools::getAccessibleObjectForPredicate( + const uno::Reference<accessibility::XAccessible>& xAcc, + const std::function<bool(const uno::Reference<accessibility::XAccessibleContext>&)>& cPredicate) +{ + return getAccessibleObjectForPredicate(xAcc->getAccessibleContext(), cPredicate); +} + +uno::Reference<accessibility::XAccessibleContext> AccessibilityTools::getAccessibleObjectForRole( + const uno::Reference<accessibility::XAccessibleContext>& xCtx, sal_Int16 role) +{ + return getAccessibleObjectForPredicate( + xCtx, [&role](const uno::Reference<accessibility::XAccessibleContext>& xObjCtx) { + return (xObjCtx->getAccessibleRole() == role + && xObjCtx->getAccessibleStateSet() + & accessibility::AccessibleStateType::SHOWING); + }); +} + +css::uno::Reference<css::accessibility::XAccessibleContext> +AccessibilityTools::getAccessibleObjectForRole( + const css::uno::Reference<css::accessibility::XAccessible>& xacc, sal_Int16 role) +{ + return getAccessibleObjectForRole(xacc->getAccessibleContext(), role); +} + +/* this is basically the same as getAccessibleObjectForPredicate() but specialized for efficiency, + * and because the template version will not work with getAccessibleObjectForPredicate() anyway */ +css::uno::Reference<css::accessibility::XAccessibleContext> +AccessibilityTools::getAccessibleObjectForName( + const css::uno::Reference<css::accessibility::XAccessibleContext>& xCtx, const sal_Int16 role, + std::u16string_view name) +{ + if (xCtx->getAccessibleRole() == role && nameEquals(xCtx, name)) + return xCtx; + + auto nChildren = xCtx->getAccessibleChildCount(); + for (decltype(nChildren) i = 0; i < nChildren && i < AccessibilityTools::MAX_CHILDREN; i++) + { + if (auto xMatchChild = getAccessibleObjectForName(xCtx->getAccessibleChild(i), role, name)) + return xMatchChild; + } + + return nullptr; +} + +bool AccessibilityTools::equals(const uno::Reference<accessibility::XAccessible>& xacc1, + const uno::Reference<accessibility::XAccessible>& xacc2) +{ + if (!xacc1.is() || !xacc2.is()) + return xacc1.is() == xacc2.is(); + return equals(xacc1->getAccessibleContext(), xacc2->getAccessibleContext()); +} + +bool AccessibilityTools::equals(const uno::Reference<accessibility::XAccessibleContext>& xctx1, + const uno::Reference<accessibility::XAccessibleContext>& xctx2) +{ + if (!xctx1.is() || !xctx2.is()) + return xctx1.is() == xctx2.is(); + + if (xctx1->getAccessibleRole() != xctx2->getAccessibleRole()) + return false; + + if (xctx1->getAccessibleName() != xctx2->getAccessibleName()) + return false; + + if (xctx1->getAccessibleDescription() != xctx2->getAccessibleDescription()) + return false; + + if (xctx1->getAccessibleChildCount() != xctx2->getAccessibleChildCount()) + return false; + + /* this one was not in the Java version */ + if (xctx1->getAccessibleIndexInParent() != xctx2->getAccessibleIndexInParent()) + return false; + + /* because in Writer at least some children only are referenced by their relations to others + * objects, we need to account for that as their index in parent is incorrect (so not + * necessarily unique) */ + auto relset1 = xctx1->getAccessibleRelationSet(); + auto relset2 = xctx2->getAccessibleRelationSet(); + if (relset1.is() != relset2.is()) + return false; + else if (relset1.is()) + { + auto relCount1 = relset1->getRelationCount(); + auto relCount2 = relset2->getRelationCount(); + if (relCount1 != relCount2) + return false; + + for (sal_Int32 i = 0; i < relCount1; ++i) + { + if (relset1->getRelation(i) != relset2->getRelation(i)) + return false; + } + } + + return equals(xctx1->getAccessibleParent(), xctx2->getAccessibleParent()); +} + +bool AccessibilityTools::nameEquals(const uno::Reference<accessibility::XAccessibleContext>& xCtx, + const std::u16string_view name) +{ + auto ctxName = xCtx->getAccessibleName(); + std::u16string_view rest; + + if (!o3tl::starts_with(ctxName, name, &rest)) + return false; + if (rest == u"") + return true; + +#if defined(_WIN32) + // see OAccessibleMenuItemComponent::GetAccessibleName(): + // on Win32, ignore a \tSHORTCUT suffix on a menu item + switch (xCtx->getAccessibleRole()) + { + case accessibility::AccessibleRole::MENU_ITEM: + case accessibility::AccessibleRole::RADIO_MENU_ITEM: + case accessibility::AccessibleRole::CHECK_MENU_ITEM: + return rest[0] == '\t'; + + default: + break; + } +#endif + +#if OSL_DEBUG_LEVEL > 0 + // see VCLXAccessibleComponent::getAccessibleName() + static const char* pEnvAppendType = getenv("LIBO_APPEND_WINDOW_TYPE_TO_ACCESSIBLE_NAME"); + if (pEnvAppendType && OUString::createFromAscii(pEnvAppendType) != u"0") + { + auto pVCLXAccessibleComponent = dynamic_cast<VCLXAccessibleComponent*>(xCtx.get()); + if (pVCLXAccessibleComponent) + { + auto windowType = pVCLXAccessibleComponent->GetWindow()->GetType(); + if (rest + == Concat2View(u" (Type = " + OUString::number(static_cast<sal_Int32>(windowType)) + + ")")) + return true; + } + } +#endif + return false; +} + +static OUString unknownName(const sal_Int64 value) +{ + return "unknown (" + OUString::number(value) + ")"; +} + +OUString AccessibilityTools::getRoleName(const sal_Int16 role) +{ + switch (role) + { + case accessibility::AccessibleRole::UNKNOWN: + return "UNKNOWN"; + case accessibility::AccessibleRole::ALERT: + return "ALERT"; + case accessibility::AccessibleRole::BLOCK_QUOTE: + return "BLOCK_QUOTE"; + case accessibility::AccessibleRole::BUTTON_DROPDOWN: + return "BUTTON_DROPDOWN"; + case accessibility::AccessibleRole::BUTTON_MENU: + return "BUTTON_MENU"; + case accessibility::AccessibleRole::CANVAS: + return "CANVAS"; + case accessibility::AccessibleRole::CAPTION: + return "CAPTION"; + case accessibility::AccessibleRole::CHART: + return "CHART"; + case accessibility::AccessibleRole::CHECK_BOX: + return "CHECK_BOX"; + case accessibility::AccessibleRole::CHECK_MENU_ITEM: + return "CHECK_MENU_ITEM"; + case accessibility::AccessibleRole::COLOR_CHOOSER: + return "COLOR_CHOOSER"; + case accessibility::AccessibleRole::COLUMN_HEADER: + return "COLUMN_HEADER"; + case accessibility::AccessibleRole::COMBO_BOX: + return "COMBO_BOX"; + case accessibility::AccessibleRole::COMMENT: + return "COMMENT"; + case accessibility::AccessibleRole::COMMENT_END: + return "COMMENT_END"; + case accessibility::AccessibleRole::DATE_EDITOR: + return "DATE_EDITOR"; + case accessibility::AccessibleRole::DESKTOP_ICON: + return "DESKTOP_ICON"; + case accessibility::AccessibleRole::DESKTOP_PANE: + return "DESKTOP_PANE"; + case accessibility::AccessibleRole::DIALOG: + return "DIALOG"; + case accessibility::AccessibleRole::DIRECTORY_PANE: + return "DIRECTORY_PANE"; + case accessibility::AccessibleRole::DOCUMENT: + return "DOCUMENT"; + case accessibility::AccessibleRole::DOCUMENT_PRESENTATION: + return "DOCUMENT_PRESENTATION"; + case accessibility::AccessibleRole::DOCUMENT_SPREADSHEET: + return "DOCUMENT_SPREADSHEET"; + case accessibility::AccessibleRole::DOCUMENT_TEXT: + return "DOCUMENT_TEXT"; + case accessibility::AccessibleRole::EDIT_BAR: + return "EDIT_BAR"; + case accessibility::AccessibleRole::EMBEDDED_OBJECT: + return "EMBEDDED_OBJECT"; + case accessibility::AccessibleRole::END_NOTE: + return "END_NOTE"; + case accessibility::AccessibleRole::FILE_CHOOSER: + return "FILE_CHOOSER"; + case accessibility::AccessibleRole::FILLER: + return "FILLER"; + case accessibility::AccessibleRole::FONT_CHOOSER: + return "FONT_CHOOSER"; + case accessibility::AccessibleRole::FOOTER: + return "FOOTER"; + case accessibility::AccessibleRole::FOOTNOTE: + return "FOOTNOTE"; + case accessibility::AccessibleRole::FORM: + return "FORM"; + case accessibility::AccessibleRole::FRAME: + return "FRAME"; + case accessibility::AccessibleRole::GLASS_PANE: + return "GLASS_PANE"; + case accessibility::AccessibleRole::GRAPHIC: + return "GRAPHIC"; + case accessibility::AccessibleRole::GROUP_BOX: + return "GROUP_BOX"; + case accessibility::AccessibleRole::HEADER: + return "HEADER"; + case accessibility::AccessibleRole::HEADING: + return "HEADING"; + case accessibility::AccessibleRole::HYPER_LINK: + return "HYPER_LINK"; + case accessibility::AccessibleRole::ICON: + return "ICON"; + case accessibility::AccessibleRole::IMAGE_MAP: + return "IMAGE_MAP"; + case accessibility::AccessibleRole::INTERNAL_FRAME: + return "INTERNAL_FRAME"; + case accessibility::AccessibleRole::LABEL: + return "LABEL"; + case accessibility::AccessibleRole::LAYERED_PANE: + return "LAYERED_PANE"; + case accessibility::AccessibleRole::LIST: + return "LIST"; + case accessibility::AccessibleRole::LIST_ITEM: + return "LIST_ITEM"; + case accessibility::AccessibleRole::MENU: + return "MENU"; + case accessibility::AccessibleRole::MENU_BAR: + return "MENU_BAR"; + case accessibility::AccessibleRole::MENU_ITEM: + return "MENU_ITEM"; + case accessibility::AccessibleRole::NOTE: + return "NOTE"; + case accessibility::AccessibleRole::OPTION_PANE: + return "OPTION_PANE"; + case accessibility::AccessibleRole::PAGE: + return "PAGE"; + case accessibility::AccessibleRole::PAGE_TAB: + return "PAGE_TAB"; + case accessibility::AccessibleRole::PAGE_TAB_LIST: + return "PAGE_TAB_LIST"; + case accessibility::AccessibleRole::PANEL: + return "PANEL"; + case accessibility::AccessibleRole::PARAGRAPH: + return "PARAGRAPH"; + case accessibility::AccessibleRole::PASSWORD_TEXT: + return "PASSWORD_TEXT"; + case accessibility::AccessibleRole::POPUP_MENU: + return "POPUP_MENU"; + case accessibility::AccessibleRole::PROGRESS_BAR: + return "PROGRESS_BAR"; + case accessibility::AccessibleRole::PUSH_BUTTON: + return "PUSH_BUTTON"; + case accessibility::AccessibleRole::RADIO_BUTTON: + return "RADIO_BUTTON"; + case accessibility::AccessibleRole::RADIO_MENU_ITEM: + return "RADIO_MENU_ITEM"; + case accessibility::AccessibleRole::ROOT_PANE: + return "ROOT_PANE"; + case accessibility::AccessibleRole::ROW_HEADER: + return "ROW_HEADER"; + case accessibility::AccessibleRole::RULER: + return "RULER"; + case accessibility::AccessibleRole::SCROLL_BAR: + return "SCROLL_BAR"; + case accessibility::AccessibleRole::SCROLL_PANE: + return "SCROLL_PANE"; + case accessibility::AccessibleRole::SECTION: + return "SECTION"; + case accessibility::AccessibleRole::SEPARATOR: + return "SEPARATOR"; + case accessibility::AccessibleRole::SHAPE: + return "SHAPE"; + case accessibility::AccessibleRole::SLIDER: + return "SLIDER"; + case accessibility::AccessibleRole::SPIN_BOX: + return "SPIN_BOX"; + case accessibility::AccessibleRole::SPLIT_PANE: + return "SPLIT_PANE"; + case accessibility::AccessibleRole::STATIC: + return "STATIC"; + case accessibility::AccessibleRole::STATUS_BAR: + return "STATUS_BAR"; + case accessibility::AccessibleRole::TABLE: + return "TABLE"; + case accessibility::AccessibleRole::TABLE_CELL: + return "TABLE_CELL"; + case accessibility::AccessibleRole::TEXT: + return "TEXT"; + case accessibility::AccessibleRole::TEXT_FRAME: + return "TEXT_FRAME"; + case accessibility::AccessibleRole::TOGGLE_BUTTON: + return "TOGGLE_BUTTON"; + case accessibility::AccessibleRole::TOOL_BAR: + return "TOOL_BAR"; + case accessibility::AccessibleRole::TOOL_TIP: + return "TOOL_TIP"; + case accessibility::AccessibleRole::TREE: + return "TREE"; + case accessibility::AccessibleRole::TREE_ITEM: + return "TREE_ITEM"; + case accessibility::AccessibleRole::TREE_TABLE: + return "TREE_TABLE"; + case accessibility::AccessibleRole::VIEW_PORT: + return "VIEW_PORT"; + case accessibility::AccessibleRole::WINDOW: + return "WINDOW"; + }; + return unknownName(role); +} + +OUString AccessibilityTools::debugAccessibleStateSet(const sal_Int64 nCombinedState) +{ + OUString combinedName; + + for (int i = 0; i < 63; i++) + { + sal_Int64 state = sal_Int64(1) << i; + if (!(state & nCombinedState)) + continue; + OUString name; + switch (state) + { + case accessibility::AccessibleStateType::ACTIVE: + name = "ACTIVE"; + break; + case accessibility::AccessibleStateType::ARMED: + name = "ARMED"; + break; + case accessibility::AccessibleStateType::BUSY: + name = "BUSY"; + break; + case accessibility::AccessibleStateType::CHECKABLE: + name = "CHECKABLE"; + break; + case accessibility::AccessibleStateType::CHECKED: + name = "CHECKED"; + break; + case accessibility::AccessibleStateType::COLLAPSE: + name = "COLLAPSE"; + break; + case accessibility::AccessibleStateType::DEFAULT: + name = "DEFAULT"; + break; + case accessibility::AccessibleStateType::DEFUNC: + name = "DEFUNC"; + break; + case accessibility::AccessibleStateType::EDITABLE: + name = "EDITABLE"; + break; + case accessibility::AccessibleStateType::ENABLED: + name = "ENABLED"; + break; + case accessibility::AccessibleStateType::EXPANDABLE: + name = "EXPANDABLE"; + break; + case accessibility::AccessibleStateType::EXPANDED: + name = "EXPANDED"; + break; + case accessibility::AccessibleStateType::FOCUSABLE: + name = "FOCUSABLE"; + break; + case accessibility::AccessibleStateType::FOCUSED: + name = "FOCUSED"; + break; + case accessibility::AccessibleStateType::HORIZONTAL: + name = "HORIZONTAL"; + break; + case accessibility::AccessibleStateType::ICONIFIED: + name = "ICONIFIED"; + break; + case accessibility::AccessibleStateType::INDETERMINATE: + name = "INDETERMINATE"; + break; + case accessibility::AccessibleStateType::INVALID: + name = "INVALID"; + break; + case accessibility::AccessibleStateType::MANAGES_DESCENDANTS: + name = "MANAGES_DESCENDANTS"; + break; + case accessibility::AccessibleStateType::MODAL: + name = "MODAL"; + break; + case accessibility::AccessibleStateType::MOVEABLE: + name = "MOVEABLE"; + break; + case accessibility::AccessibleStateType::MULTI_LINE: + name = "MULTI_LINE"; + break; + case accessibility::AccessibleStateType::MULTI_SELECTABLE: + name = "MULTI_SELECTABLE"; + break; + case accessibility::AccessibleStateType::OFFSCREEN: + name = "OFFSCREEN"; + break; + case accessibility::AccessibleStateType::OPAQUE: + name = "OPAQUE"; + break; + case accessibility::AccessibleStateType::PRESSED: + name = "PRESSED"; + break; + case accessibility::AccessibleStateType::RESIZABLE: + name = "RESIZABLE"; + break; + case accessibility::AccessibleStateType::SELECTABLE: + name = "SELECTABLE"; + break; + case accessibility::AccessibleStateType::SELECTED: + name = "SELECTED"; + break; + case accessibility::AccessibleStateType::SENSITIVE: + name = "SENSITIVE"; + break; + case accessibility::AccessibleStateType::SHOWING: + name = "SHOWING"; + break; + case accessibility::AccessibleStateType::SINGLE_LINE: + name = "SINGLE_LINE"; + break; + case accessibility::AccessibleStateType::STALE: + name = "STALE"; + break; + case accessibility::AccessibleStateType::TRANSIENT: + name = "TRANSIENT"; + break; + case accessibility::AccessibleStateType::VERTICAL: + name = "VERTICAL"; + break; + case accessibility::AccessibleStateType::VISIBLE: + name = "VISIBLE"; + break; + default: + name = unknownName(state); + break; + } + if (combinedName.getLength()) + combinedName += " | "; + combinedName += name; + } + + if (combinedName.isEmpty()) + return "unknown"; + return combinedName; +} + +OUString AccessibilityTools::getEventIdName(const sal_Int16 event_id) +{ + switch (event_id) + { + case accessibility::AccessibleEventId::ACTION_CHANGED: + return "ACTION_CHANGED"; + case accessibility::AccessibleEventId::ACTIVE_DESCENDANT_CHANGED: + return "ACTIVE_DESCENDANT_CHANGED"; + case accessibility::AccessibleEventId::ACTIVE_DESCENDANT_CHANGED_NOFOCUS: + return "ACTIVE_DESCENDANT_CHANGED_NOFOCUS"; + case accessibility::AccessibleEventId::BOUNDRECT_CHANGED: + return "BOUNDRECT_CHANGED"; + case accessibility::AccessibleEventId::CARET_CHANGED: + return "CARET_CHANGED"; + case accessibility::AccessibleEventId::CHILD: + return "CHILD"; + case accessibility::AccessibleEventId::COLUMN_CHANGED: + return "COLUMN_CHANGED"; + case accessibility::AccessibleEventId::CONTENT_FLOWS_FROM_RELATION_CHANGED: + return "CONTENT_FLOWS_FROM_RELATION_CHANGED"; + case accessibility::AccessibleEventId::CONTENT_FLOWS_TO_RELATION_CHANGED: + return "CONTENT_FLOWS_TO_RELATION_CHANGED"; + case accessibility::AccessibleEventId::CONTROLLED_BY_RELATION_CHANGED: + return "CONTROLLED_BY_RELATION_CHANGED"; + case accessibility::AccessibleEventId::CONTROLLER_FOR_RELATION_CHANGED: + return "CONTROLLER_FOR_RELATION_CHANGED"; + case accessibility::AccessibleEventId::DESCRIPTION_CHANGED: + return "DESCRIPTION_CHANGED"; + case accessibility::AccessibleEventId::HYPERTEXT_CHANGED: + return "HYPERTEXT_CHANGED"; + case accessibility::AccessibleEventId::INVALIDATE_ALL_CHILDREN: + return "INVALIDATE_ALL_CHILDREN"; + case accessibility::AccessibleEventId::LABELED_BY_RELATION_CHANGED: + return "LABELED_BY_RELATION_CHANGED"; + case accessibility::AccessibleEventId::LABEL_FOR_RELATION_CHANGED: + return "LABEL_FOR_RELATION_CHANGED"; + case accessibility::AccessibleEventId::LISTBOX_ENTRY_COLLAPSED: + return "LISTBOX_ENTRY_COLLAPSED"; + case accessibility::AccessibleEventId::LISTBOX_ENTRY_EXPANDED: + return "LISTBOX_ENTRY_EXPANDED"; + case accessibility::AccessibleEventId::MEMBER_OF_RELATION_CHANGED: + return "MEMBER_OF_RELATION_CHANGED"; + case accessibility::AccessibleEventId::NAME_CHANGED: + return "NAME_CHANGED"; + case accessibility::AccessibleEventId::PAGE_CHANGED: + return "PAGE_CHANGED"; + case accessibility::AccessibleEventId::ROLE_CHANGED: + return "ROLE_CHANGED"; + case accessibility::AccessibleEventId::SECTION_CHANGED: + return "SECTION_CHANGED"; + case accessibility::AccessibleEventId::SELECTION_CHANGED: + return "SELECTION_CHANGED"; + case accessibility::AccessibleEventId::SELECTION_CHANGED_ADD: + return "SELECTION_CHANGED_ADD"; + case accessibility::AccessibleEventId::SELECTION_CHANGED_REMOVE: + return "SELECTION_CHANGED_REMOVE"; + case accessibility::AccessibleEventId::SELECTION_CHANGED_WITHIN: + return "SELECTION_CHANGED_WITHIN"; + case accessibility::AccessibleEventId::STATE_CHANGED: + return "STATE_CHANGED"; + case accessibility::AccessibleEventId::SUB_WINDOW_OF_RELATION_CHANGED: + return "SUB_WINDOW_OF_RELATION_CHANGED"; + case accessibility::AccessibleEventId::TABLE_CAPTION_CHANGED: + return "TABLE_CAPTION_CHANGED"; + case accessibility::AccessibleEventId::TABLE_COLUMN_DESCRIPTION_CHANGED: + return "TABLE_COLUMN_DESCRIPTION_CHANGED"; + case accessibility::AccessibleEventId::TABLE_COLUMN_HEADER_CHANGED: + return "TABLE_COLUMN_HEADER_CHANGED"; + case accessibility::AccessibleEventId::TABLE_MODEL_CHANGED: + return "TABLE_MODEL_CHANGED"; + case accessibility::AccessibleEventId::TABLE_ROW_DESCRIPTION_CHANGED: + return "TABLE_ROW_DESCRIPTION_CHANGED"; + case accessibility::AccessibleEventId::TABLE_ROW_HEADER_CHANGED: + return "TABLE_ROW_HEADER_CHANGED"; + case accessibility::AccessibleEventId::TABLE_SUMMARY_CHANGED: + return "TABLE_SUMMARY_CHANGED"; + case accessibility::AccessibleEventId::TEXT_ATTRIBUTE_CHANGED: + return "TEXT_ATTRIBUTE_CHANGED"; + case accessibility::AccessibleEventId::TEXT_CHANGED: + return "TEXT_CHANGED"; + case accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED: + return "TEXT_SELECTION_CHANGED"; + case accessibility::AccessibleEventId::VALUE_CHANGED: + return "VALUE_CHANGED"; + case accessibility::AccessibleEventId::VISIBLE_DATA_CHANGED: + return "VISIBLE_DATA_CHANGED"; + } + return unknownName(event_id); +} + +OUString AccessibilityTools::getRelationTypeName(const sal_Int16 rel_type) +{ + switch (rel_type) + { + case accessibility::AccessibleRelationType::CONTENT_FLOWS_FROM: + return "CONTENT_FLOWS_FROM"; + case accessibility::AccessibleRelationType::CONTENT_FLOWS_TO: + return "CONTENT_FLOWS_TO"; + case accessibility::AccessibleRelationType::CONTROLLED_BY: + return "CONTROLLED_BY"; + case accessibility::AccessibleRelationType::CONTROLLER_FOR: + return "CONTROLLER_FOR"; + case accessibility::AccessibleRelationType::DESCRIBED_BY: + return "DESCRIBED_BY"; + case accessibility::AccessibleRelationType::INVALID: + return "INVALID"; + case accessibility::AccessibleRelationType::LABELED_BY: + return "LABELED_BY"; + case accessibility::AccessibleRelationType::LABEL_FOR: + return "LABEL_FOR"; + case accessibility::AccessibleRelationType::MEMBER_OF: + return "MEMBER_OF"; + case accessibility::AccessibleRelationType::NODE_CHILD_OF: + return "NODE_CHILD_OF"; + case accessibility::AccessibleRelationType::SUB_WINDOW_OF: + return "SUB_WINDOW_OF"; + } + return unknownName(rel_type); +} + +OUString AccessibilityTools::debugName(accessibility::XAccessibleContext* ctx) +{ + return "role=" + AccessibilityTools::getRoleName(ctx->getAccessibleRole()) + " name=\"" + + ctx->getAccessibleName() + "\" description=\"" + ctx->getAccessibleDescription() + + "\""; +} + +OUString AccessibilityTools::debugName(accessibility::XAccessible* acc) +{ + return debugName(acc->getAccessibleContext().get()); +} + +OUString AccessibilityTools::debugName(accessibility::XAccessibleAction* xAct) +{ + OUStringBuffer r = "actions=["; + + const sal_Int32 nActions = xAct->getAccessibleActionCount(); + for (sal_Int32 i = 0; i < nActions; i++) + { + if (i > 0) + r.append(", "); + + r.append("description=\"" + xAct->getAccessibleActionDescription(i) + "\""); + + const auto& xKeyBinding = xAct->getAccessibleActionKeyBinding(i); + if (xKeyBinding) + { + r.append(" keybindings=["); + const sal_Int32 nKeyBindings = xKeyBinding->getAccessibleKeyBindingCount(); + for (sal_Int32 j = 0; j < nKeyBindings; j++) + { + if (j > 0) + r.append(", "); + + int k = 0; + for (const auto& keyStroke : xKeyBinding->getAccessibleKeyBinding(j)) + { + if (k++ > 0) + r.append(", "); + + r.append('"'); + if (keyStroke.Modifiers & awt::KeyModifier::MOD1) + r.append("<Mod1>"); + if (keyStroke.Modifiers & awt::KeyModifier::MOD2) + r.append("<Mod2>"); + if (keyStroke.Modifiers & awt::KeyModifier::MOD3) + r.append("<Mod3>"); + if (keyStroke.Modifiers & awt::KeyModifier::SHIFT) + r.append("<Shift>"); + r.append(OUStringChar(keyStroke.KeyChar) + "\""); + } + } + r.append("]"); + } + } + r.append("]"); + return r.makeStringAndClear(); +} + +OUString AccessibilityTools::debugName(accessibility::XAccessibleText* xTxt) +{ + uno::Reference<accessibility::XAccessibleContext> xCtx(xTxt, uno::UNO_QUERY); + return debugName(xCtx.get()); +} + +OUString AccessibilityTools::debugName(const accessibility::AccessibleEventObject* evobj) +{ + return "(AccessibleEventObject) { id=" + getEventIdName(evobj->EventId) + + " old=" + evobj->OldValue.getValueTypeName() + + " new=" + evobj->NewValue.getValueTypeName() + " }"; +} + +bool AccessibilityTools::Await(const std::function<bool()>& cUntilCallback, sal_uInt64 nTimeoutMs) +{ + bool success = false; + Timer aTimer("wait for event"); + aTimer.SetTimeout(nTimeoutMs); + aTimer.Start(); + do + { + Scheduler::ProcessEventsToIdle(); + success = cUntilCallback(); + } while (!success && aTimer.IsActive()); + SAL_WARN_IF(!success, "test", "timeout reached"); + return success; +} + +void AccessibilityTools::Wait(sal_uInt64 nTimeoutMs) +{ + Timer aTimer("wait for event"); + aTimer.SetTimeout(nTimeoutMs); + aTimer.Start(); + std::cout << "waiting for " << nTimeoutMs << "ms... "; + do + { + Scheduler::ProcessEventsToIdle(); + } while (aTimer.IsActive()); + std::cout << "ok." << std::endl; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ |