diff options
author | Samuel Thibault <sthibault@hypra.fr> | 2018-03-21 15:30:00 +0100 |
---|---|---|
committer | Thorsten Behrens <Thorsten.Behrens@CIB.de> | 2018-08-21 03:12:21 +0200 |
commit | 5732db01795df90df95944cffc8566ea11e6c389 (patch) | |
tree | dcc1f9cfd5b627ebf49f25fbee3104a6ef0c5777 /vcl | |
parent | 414ef6cb187dd3bbcc917dbedf3c0c1cc8668f60 (diff) |
tdf#116542 a11y: Implement .ui ways of setting widget role
Atk-LO correspondance in getRoleFromName() was built on
vcl/unx/gtk/a11y/atkwrapper.cxx's correspondance, with the same "?"
uncertainties, plus some approximations.
Change-Id: I2e3a5042d4c9dabbab5407397373a373ee1caa6d
Reviewed-on: https://gerrit.libreoffice.org/58767
Tested-by: Jenkins
Reviewed-by: Thorsten Behrens <Thorsten.Behrens@CIB.de>
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/source/window/builder.cxx | 199 | ||||
-rw-r--r-- | vcl/source/window/window2.cxx | 9 |
2 files changed, 193 insertions, 15 deletions
diff --git a/vcl/source/window/builder.cxx b/vcl/source/window/builder.cxx index b08d84a28cc6..0394261e0248 100644 --- a/vcl/source/window/builder.cxx +++ b/vcl/source/window/builder.cxx @@ -8,6 +8,7 @@ */ #include <memory> +#include <unordered_map> #include <com/sun/star/accessibility/AccessibleRole.hpp> #include <com/sun/star/packages/zip/ZipFileAccess.hpp> @@ -380,7 +381,7 @@ VclBuilder::VclBuilder(vcl::Window *pParent, const OUString& sUIDir, const OUStr pOne->set_mnemonic_widget(pOther); } - //Set a11y relations when everything has been imported + //Set a11y relations and role when everything has been imported for (auto const& elemAtk : m_pParserState->m_aAtkInfo) { vcl::Window *pSource = elemAtk.first; @@ -388,21 +389,30 @@ VclBuilder::VclBuilder(vcl::Window *pParent, const OUString& sUIDir, const OUStr for (auto const& elemMap : rMap) { - const OUString &rTarget = elemMap.second; - vcl::Window *pTarget = get<vcl::Window>(rTarget.toUtf8()); - SAL_WARN_IF(!pTarget, "vcl", "missing member of a11y relation: " << rTarget); - if (!pTarget) - continue; const OString &rType = elemMap.first; - if (rType == "labelled-by") - pSource->SetAccessibleRelationLabeledBy(pTarget); - else if (rType == "label-for") - pSource->SetAccessibleRelationLabelFor(pTarget); - else if (rType == "member-of") - pSource->SetAccessibleRelationMemberOf(pTarget); + const OUString &rParam = elemMap.second; + if (rType == "role") + { + sal_Int16 role = BuilderUtils::getRoleFromName(rParam.toUtf8()); + if (role != com::sun::star::accessibility::AccessibleRole::UNKNOWN) + pSource->SetAccessibleRole(role); + } else { - SAL_INFO("vcl.layout", "unhandled a11y relation :" << rType); + vcl::Window *pTarget = get<vcl::Window>(rParam.toUtf8()); + SAL_WARN_IF(!pTarget, "vcl", "missing parameter of a11y relation: " << rParam); + if (!pTarget) + continue; + if (rType == "labelled-by") + pSource->SetAccessibleRelationLabeledBy(pTarget); + else if (rType == "label-for") + pSource->SetAccessibleRelationLabelFor(pTarget); + else if (rType == "member-of") + pSource->SetAccessibleRelationMemberOf(pTarget); + else + { + SAL_WARN("vcl.layout", "unhandled a11y relation :" << rType); + } } } } @@ -2096,6 +2106,143 @@ namespace BuilderUtils rChilds[i]->SetStyle(nBits); } } + + sal_Int16 getRoleFromName(const OString& roleName) + { + using namespace com::sun::star::accessibility; + + static const std::unordered_map<OString, sal_Int16, OStringHash> aAtkRoleToAccessibleRole = { + /* This is in atkobject.h's AtkRole order */ + { "invalid", AccessibleRole::UNKNOWN }, + { "accelerator label", AccessibleRole::UNKNOWN }, + { "alert", AccessibleRole::ALERT }, + { "animation", AccessibleRole::UNKNOWN }, + { "arrow", AccessibleRole::UNKNOWN }, + { "calendar", AccessibleRole::UNKNOWN }, + { "canvas", AccessibleRole::CANVAS }, + { "check box", AccessibleRole::CHECK_BOX }, + { "check menu item", AccessibleRole::CHECK_MENU_ITEM }, + { "color chooser", AccessibleRole::COLOR_CHOOSER }, + { "column header", AccessibleRole::COLUMN_HEADER }, + { "combo box", AccessibleRole::COMBO_BOX }, + { "date editor", AccessibleRole::DATE_EDITOR }, + { "desktop icon", AccessibleRole::DESKTOP_ICON }, + { "desktop frame", AccessibleRole::DESKTOP_PANE }, // ? + { "dial", AccessibleRole::UNKNOWN }, + { "dialog", AccessibleRole::DIALOG }, + { "directory pane", AccessibleRole::DIRECTORY_PANE }, + { "drawing area", AccessibleRole::UNKNOWN }, + { "file chooser", AccessibleRole::FILE_CHOOSER }, + { "filler", AccessibleRole::FILLER }, + { "font chooser", AccessibleRole::FONT_CHOOSER }, + { "frame", AccessibleRole::FRAME }, + { "glass pane", AccessibleRole::GLASS_PANE }, + { "html container", AccessibleRole::UNKNOWN }, + { "icon", AccessibleRole::ICON }, + { "image", AccessibleRole::GRAPHIC }, + { "internal frame", AccessibleRole::INTERNAL_FRAME }, + { "label", AccessibleRole::LABEL }, + { "layered pane", AccessibleRole::LAYERED_PANE }, + { "list", AccessibleRole::LIST }, + { "list item", AccessibleRole::LIST_ITEM }, + { "menu", AccessibleRole::MENU }, + { "menu bar", AccessibleRole::MENU_BAR }, + { "menu item", AccessibleRole::MENU_ITEM }, + { "option pane", AccessibleRole::OPTION_PANE }, + { "page tab", AccessibleRole::PAGE_TAB }, + { "page tab list", AccessibleRole::PAGE_TAB_LIST }, + { "panel", AccessibleRole::PANEL }, // or SHAPE or TEXT_FRAME ? + { "password text", AccessibleRole::PASSWORD_TEXT }, + { "popup menu", AccessibleRole::POPUP_MENU }, + { "progress bar", AccessibleRole::PROGRESS_BAR }, + { "push button", AccessibleRole::PUSH_BUTTON }, // or BUTTON_DROPDOWN or BUTTON_MENU + { "radio button", AccessibleRole::RADIO_BUTTON }, + { "radio menu item", AccessibleRole::RADIO_MENU_ITEM }, + { "root pane", AccessibleRole::ROOT_PANE }, + { "row header", AccessibleRole::ROW_HEADER }, + { "scroll bar", AccessibleRole::SCROLL_BAR }, + { "scroll pane", AccessibleRole::SCROLL_PANE }, + { "separator", AccessibleRole::SEPARATOR }, + { "slider", AccessibleRole::SLIDER }, + { "split pane", AccessibleRole::SPLIT_PANE }, + { "spin button", AccessibleRole::SPIN_BOX }, // ? + { "statusbar", AccessibleRole::STATUS_BAR }, + { "table", AccessibleRole::TABLE }, + { "table cell", AccessibleRole::TABLE_CELL }, + { "table column header", AccessibleRole::COLUMN_HEADER }, // approximate + { "table row header", AccessibleRole::ROW_HEADER }, // approximate + { "tear off menu item", AccessibleRole::UNKNOWN }, + { "terminal", AccessibleRole::UNKNOWN }, + { "text", AccessibleRole::TEXT }, + { "toggle button", AccessibleRole::TOGGLE_BUTTON }, + { "tool bar", AccessibleRole::TOOL_BAR }, + { "tool tip", AccessibleRole::TOOL_TIP }, + { "tree", AccessibleRole::TREE }, + { "tree table", AccessibleRole::TREE_TABLE }, + { "unknown", AccessibleRole::UNKNOWN }, + { "viewport", AccessibleRole::VIEW_PORT }, + { "window", AccessibleRole::WINDOW }, + { "header", AccessibleRole::HEADER }, + { "footer", AccessibleRole::FOOTER }, + { "paragraph", AccessibleRole::PARAGRAPH }, + { "ruler", AccessibleRole::RULER }, + { "application", AccessibleRole::UNKNOWN }, + { "autocomplete", AccessibleRole::UNKNOWN }, + { "edit bar", AccessibleRole::EDIT_BAR }, + { "embedded", AccessibleRole::EMBEDDED_OBJECT }, + { "entry", AccessibleRole::UNKNOWN }, + { "chart", AccessibleRole::CHART }, + { "caption", AccessibleRole::CAPTION }, + { "document frame", AccessibleRole::DOCUMENT }, + { "heading", AccessibleRole::HEADING }, + { "page", AccessibleRole::PAGE }, + { "section", AccessibleRole::SECTION }, + { "redundant object", AccessibleRole::UNKNOWN }, + { "form", AccessibleRole::FORM }, + { "link", AccessibleRole::HYPER_LINK }, + { "input method window", AccessibleRole::UNKNOWN }, + { "table row", AccessibleRole::UNKNOWN }, + { "tree item", AccessibleRole::TREE_ITEM }, + { "document spreadsheet", AccessibleRole::DOCUMENT_SPREADSHEET }, + { "document presentation", AccessibleRole::DOCUMENT_PRESENTATION }, + { "document text", AccessibleRole::DOCUMENT_TEXT }, + { "document web", AccessibleRole::DOCUMENT }, // approximate + { "document email", AccessibleRole::DOCUMENT }, // approximate + { "comment", AccessibleRole::COMMENT }, // or NOTE or END_NOTE or FOOTNOTE or SCROLL_PANE + { "list box", AccessibleRole::UNKNOWN }, + { "grouping", AccessibleRole::GROUP_BOX }, + { "image map", AccessibleRole::IMAGE_MAP }, + { "notification", AccessibleRole::UNKNOWN }, + { "info bar", AccessibleRole::UNKNOWN }, + { "level bar", AccessibleRole::UNKNOWN }, + { "title bar", AccessibleRole::UNKNOWN }, + { "block quote", AccessibleRole::UNKNOWN }, + { "audio", AccessibleRole::UNKNOWN }, + { "video", AccessibleRole::UNKNOWN }, + { "definition", AccessibleRole::UNKNOWN }, + { "article", AccessibleRole::UNKNOWN }, + { "landmark", AccessibleRole::UNKNOWN }, + { "log", AccessibleRole::UNKNOWN }, + { "marquee", AccessibleRole::UNKNOWN }, + { "math", AccessibleRole::UNKNOWN }, + { "rating", AccessibleRole::UNKNOWN }, + { "timer", AccessibleRole::UNKNOWN }, + { "description list", AccessibleRole::UNKNOWN }, + { "description term", AccessibleRole::UNKNOWN }, + { "description value", AccessibleRole::UNKNOWN }, + { "static", AccessibleRole::STATIC }, + { "math fraction", AccessibleRole::UNKNOWN }, + { "math root", AccessibleRole::UNKNOWN }, + { "subscript", AccessibleRole::UNKNOWN }, + { "superscript", AccessibleRole::UNKNOWN }, + { "footnote", AccessibleRole::FOOTNOTE }, + }; + + auto it = aAtkRoleToAccessibleRole.find(roleName); + if (it == aAtkRoleToAccessibleRole.end()) + return AccessibleRole::UNKNOWN; + return it->second; + } } VclPtr<vcl::Window> VclBuilder::insertObject(vcl::Window *pParent, const OString &rClass, @@ -2469,7 +2616,7 @@ void VclBuilder::collectPangoAttribute(xmlreader::XmlReader &reader, stringmap & rMap[sProperty] = OUString::fromUtf8(sValue); } -void VclBuilder::collectAtkAttribute(xmlreader::XmlReader &reader, stringmap &rMap) +void VclBuilder::collectAtkRelationAttribute(xmlreader::XmlReader &reader, stringmap &rMap) { xmlreader::Span span; int nsId; @@ -2498,6 +2645,26 @@ void VclBuilder::collectAtkAttribute(xmlreader::XmlReader &reader, stringmap &rM rMap[sProperty] = OUString::fromUtf8(sValue); } +void VclBuilder::collectAtkRoleAttribute(xmlreader::XmlReader &reader, stringmap &rMap) +{ + xmlreader::Span span; + int nsId; + + OString sProperty; + + while (reader.nextAttribute(&nsId, &span)) + { + if (span.equals("type")) + { + span = reader.getAttributeValue(false); + sProperty = OString(span.begin, span.length); + } + } + + if (!sProperty.isEmpty()) + rMap["role"] = OUString::fromUtf8(sProperty); +} + void VclBuilder::handleRow(xmlreader::XmlReader &reader, const OString &rID) { int nLevel = 1; @@ -3173,7 +3340,9 @@ VclPtr<vcl::Window> VclBuilder::handleObject(vcl::Window *pParent, xmlreader::Xm else if (name.equals("attribute")) collectPangoAttribute(reader, aPangoAttributes); else if (name.equals("relation")) - collectAtkAttribute(reader, aAtkAttributes); + collectAtkRelationAttribute(reader, aAtkAttributes); + else if (name.equals("role")) + collectAtkRoleAttribute(reader, aAtkAttributes); else if (name.equals("action-widget")) handleActionWidget(reader); } diff --git a/vcl/source/window/window2.cxx b/vcl/source/window/window2.cxx index 4642b5fa820a..522b0ef8f1c3 100644 --- a/vcl/source/window/window2.cxx +++ b/vcl/source/window/window2.cxx @@ -34,6 +34,7 @@ #include <vcl/dockwin.hxx> #include <vcl/tabctrl.hxx> #include <vcl/settings.hxx> +#include <vcl/builder.hxx> #include <window.h> #include <fontinstance.hxx> @@ -44,6 +45,8 @@ #include <salframe.hxx> #include <scrwnd.hxx> +#include <com/sun/star/accessibility/AccessibleRole.hpp> + using namespace com::sun::star; namespace vcl { @@ -1582,6 +1585,12 @@ bool Window::set_property(const OString &rKey, const OUString &rValue) { SetAccessibleDescription(rValue); } + else if (rKey == "accessible-role") + { + sal_Int16 role = BuilderUtils::getRoleFromName(rValue.toUtf8()); + if (role != com::sun::star::accessibility::AccessibleRole::UNKNOWN) + SetAccessibleRole(role); + } else if (rKey == "use-markup") { //https://live.gnome.org/GnomeGoals/RemoveMarkupInMessages |