From f5883eb9060f34e1f0b6569dcfec61e6983babfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Boris=20Du=C5=A1ek?= Date: Tue, 17 Mar 2015 23:04:52 +0100 Subject: Accessibility Linux: Fix text attributes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- .../linuxaccessibility/atspiadaptor.cpp | 126 ++++++++++++++++++++- 1 file changed, 124 insertions(+), 2 deletions(-) (limited to 'src/platformsupport') 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(); -- cgit v1.2.3