diff options
author | Boris Dušek <me@dusek.me> | 2015-03-17 23:04:52 +0100 |
---|---|---|
committer | Boris Dušek <me@dusek.me> | 2015-03-25 09:48:54 +0000 |
commit | f5883eb9060f34e1f0b6569dcfec61e6983babfe (patch) | |
tree | 52063f9192a9fc15dfeb456a315b516e6f8a723d /src/platformsupport/linuxaccessibility/atspiadaptor.cpp | |
parent | 76c94be4e77bfef6ee3642cb175ff34ba6c694db (diff) |
Accessibility Linux: Fix text attributes
Orca expects text attributes with different names (and sometimes also
different values) than IAccessible2 ones (which Qt uses). So adapt the names
and values accordingly.
[ChangeLog][Accessibility] We now report text attributes correctly on Linux,
so ORCA+F now works properly in QTextEdit and other text controls.
Change-Id: Iad6d38168b309669c00069a6167f4f54cbd64cf0
Task-number: QTBUG-44479
Reviewed-by: Jan Arve Sæther <jan-arve.saether@theqtcompany.com>
Diffstat (limited to 'src/platformsupport/linuxaccessibility/atspiadaptor.cpp')
-rw-r--r-- | src/platformsupport/linuxaccessibility/atspiadaptor.cpp | 126 |
1 files changed, 124 insertions, 2 deletions
diff --git a/src/platformsupport/linuxaccessibility/atspiadaptor.cpp b/src/platformsupport/linuxaccessibility/atspiadaptor.cpp index 345fb5e2fa..c040dab5e1 100644 --- a/src/platformsupport/linuxaccessibility/atspiadaptor.cpp +++ b/src/platformsupport/linuxaccessibility/atspiadaptor.cpp @@ -1924,6 +1924,124 @@ QAccessible::TextBoundaryType AtSpiAdaptor::qAccessibleBoundaryType(int atspiTex return QAccessible::CharBoundary; } +namespace +{ + struct AtSpiAttribute { + QString name; + QString value; + AtSpiAttribute(const QString &aName, const QString &aValue) : name(aName), value(aValue) {} + bool isNull() const { return name.isNull() || value.isNull(); } + }; + + QString atspiColor(const QString &ia2Color) + { + // "rgb(%u,%u,%u)" -> "%u,%u,%u" + return ia2Color.mid(4, ia2Color.length() - (4+1)); + } + + QString atspiSize(const QString &ia2Size) + { + // "%fpt" -> "%f" + return ia2Size.left(ia2Size.length() - 2); + } + + AtSpiAttribute atspiTextAttribute(const QString &ia2Name, const QString &ia2Value) + { + QString name = ia2Name; + QString value = ia2Value; + + // IAccessible2: http://www.linuxfoundation.org/collaborate/workgroups/accessibility/iaccessible2/textattributes + // ATK attribute names: https://git.gnome.org/browse/orca/tree/src/orca/text_attribute_names.py + // ATK attribute values: https://developer.gnome.org/atk/unstable/AtkText.html#AtkTextAttribute + + // https://bugzilla.gnome.org/show_bug.cgi?id=744553 "ATK docs provide no guidance for allowed values of some text attributes" + // specifically for "weight", "invalid", "language" and value range for colors + + if (ia2Name == QStringLiteral("background-color")) { + name = QStringLiteral("bg-color"); + value = atspiColor(value); + } else if (ia2Name == QStringLiteral("font-family")) { + name = QStringLiteral("family-name"); + } else if (ia2Name == QStringLiteral("color")) { + name = QStringLiteral("fg-color"); + value = atspiColor(value); + } else if (ia2Name == QStringLiteral("text-align")) { + name = QStringLiteral("justification"); + if (value == QStringLiteral("justify")) { + value = QStringLiteral("fill"); + } else { + if (value != QStringLiteral("left") && + value != QStringLiteral("right") && + value != QStringLiteral("center") + ) { + value = QString(); + qAtspiDebug() << "Unknown text-align attribute value \"" << value << "\" cannot be translated to AT-SPI."; + } + } + } else if (ia2Name == QStringLiteral("font-size")) { + name = QStringLiteral("size"); + value = atspiSize(value); + } else if (ia2Name == QStringLiteral("font-style")) { + name = QStringLiteral("style"); + if (value != QStringLiteral("normal") && + value != QStringLiteral("italic") && + value != QStringLiteral("oblique") + ) { + value = QString(); + qAtspiDebug() << "Unknown font-style attribute value \"" << value << "\" cannot be translated to AT-SPI."; + } + } else if (ia2Name == QStringLiteral("text-underline-type")) { + name = QStringLiteral("underline"); + if (value != QStringLiteral("none") && + value != QStringLiteral("single") && + value != QStringLiteral("double") + ) { + value = QString(); + qAtspiDebug() << "Unknown text-underline-type attribute value \"" << value << "\" cannot be translated to AT-SPI."; + } + } else if (ia2Name == QStringLiteral("font-weight")) { + name = QStringLiteral("weight"); + if (value == QStringLiteral("normal")) + // Orca seems to accept all IAccessible2 values except for "normal" + // (on which it produces traceback and fails to read any following text attributes), + // but that is the default value, so omit it anyway + value = QString(); + } else if (ia2Name == QStringLiteral("text-position")) { + name = QStringLiteral("vertical-align"); + if (value != QStringLiteral("baseline") && + value != QStringLiteral("super") && + value != QStringLiteral("sub") + ) { + value = QString(); + qAtspiDebug() << "Unknown text-position attribute value \"" << value << "\" cannot be translated to AT-SPI."; + } + } else if (ia2Name == QStringLiteral("writing-mode")) { + name = QStringLiteral("direction"); + if (value == QStringLiteral("lr")) + value = QStringLiteral("ltr"); + else if (value == QStringLiteral("rl")) + value = QStringLiteral("rtl"); + else if (value == QStringLiteral("tb")) { + // IAccessible2 docs refer to XSL, which specifies "tb" is shorthand for "tb-rl"; so at least give a hint about the horizontal direction (ATK does not support vertical direction in this attribute (yet)) + value = QStringLiteral("rtl"); + qAtspiDebug() << "writing-mode attribute value \"tb\" translated only w.r.t. horizontal direction; vertical direction ignored"; + } else { + value = QString(); + qAtspiDebug() << "Unknown writing-mode attribute value \"" << value << "\" cannot be translated to AT-SPI."; + } + } else if (ia2Name == QStringLiteral("language")) { + // OK - ATK has no docs on the format of the value, IAccessible2 has reasonable format - leave it at that now + } else if (ia2Name == QStringLiteral("invalid")) { + // OK - ATK docs are vague but suggest they support the same range of values as IAccessible2 + } else { + // attribute we know nothing about + name = QString(); + value = QString(); + } + return AtSpiAttribute(name, value); + } +} + // FIXME all attribute methods below should share code QVariantList AtSpiAdaptor::getAttributes(QAccessibleInterface *interface, int offset, bool includeDefaults) const { @@ -1938,7 +2056,9 @@ QVariantList AtSpiAdaptor::getAttributes(QAccessibleInterface *interface, int of foreach (const QString &attr, attributes) { QStringList items; items = attr.split(QLatin1Char(':'), QString::SkipEmptyParts, Qt::CaseSensitive); - set[items[0]] = items[1]; + AtSpiAttribute attribute = atspiTextAttribute(items[0], items[1]); + if (!attribute.isNull()) + set[attribute.name] = attribute.value; } QVariantList list; @@ -1962,7 +2082,9 @@ QVariantList AtSpiAdaptor::getAttributeValue(QAccessibleInterface *interface, in foreach (const QString& attr, attributes) { QStringList items; items = attr.split(QLatin1Char(':'), QString::SkipEmptyParts, Qt::CaseSensitive); - map[items[0]] = items[1]; + AtSpiAttribute attribute = atspiTextAttribute(items[0], items[1]); + if (!attribute.isNull()) + map[attribute.name] = attribute.value; } mapped = map[attributeName]; defined = mapped.isEmpty(); |