summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Thibault <sthibault@hypra.fr>2018-03-21 15:30:00 +0100
committerThorsten Behrens <Thorsten.Behrens@CIB.de>2018-08-21 03:12:21 +0200
commit5732db01795df90df95944cffc8566ea11e6c389 (patch)
treedcc1f9cfd5b627ebf49f25fbee3104a6ef0c5777
parent414ef6cb187dd3bbcc917dbedf3c0c1cc8668f60 (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>
-rw-r--r--include/vcl/builder.hxx6
-rw-r--r--vcl/source/window/builder.cxx199
-rw-r--r--vcl/source/window/window2.cxx9
3 files changed, 198 insertions, 16 deletions
diff --git a/include/vcl/builder.hxx b/include/vcl/builder.hxx
index ed62d61eb397..25380a6ec5af 100644
--- a/include/vcl/builder.hxx
+++ b/include/vcl/builder.hxx
@@ -354,7 +354,8 @@ private:
void applyPackingProperty(vcl::Window *pCurrent, vcl::Window *pParent, xmlreader::XmlReader &reader);
void collectProperty(xmlreader::XmlReader &reader, stringmap &rVec) const;
static void collectPangoAttribute(xmlreader::XmlReader &reader, stringmap &rMap);
- static void collectAtkAttribute(xmlreader::XmlReader &reader, stringmap &rMap);
+ static void collectAtkRelationAttribute(xmlreader::XmlReader &reader, stringmap &rMap);
+ static void collectAtkRoleAttribute(xmlreader::XmlReader &reader, stringmap &rMap);
static void collectAccelerator(xmlreader::XmlReader &reader, accelmap &rMap);
void insertMenuObject(
@@ -411,6 +412,9 @@ namespace BuilderUtils
//Helpers to retrofit all the existing code to the builder
VCL_DLLPUBLIC void reorderWithinParent(std::vector< vcl::Window*>& rChilds, bool bIsButtonBox);
VCL_DLLPUBLIC void reorderWithinParent(vcl::Window &rWindow, sal_uInt16 nNewPosition);
+
+ //Convert an accessibility role name to accessibility role number
+ VCL_DLLPUBLIC sal_Int16 getRoleFromName(const OString& roleName);
}
template <typename T>
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