NVDA 屏幕 reader 请求错误 QAccessible::InterfaceType
NVDA screen reader requests wrong QAccessible::InterfaceType
我正在使用 Qt 5.9.1。
我正在尝试使应用程序可通过屏幕阅读器访问。我有一个包含文本(很多)的自定义小部件(我们称它为 MyWidget
)。文本是使用 QPainter
绘制的,这就是为什么使用自定义小部件而不是 QTextBrowser
.
我在派生自 QAccessibleWidget
和 QAccessibleTextInterface
的 AccessibleMyWidget
class 中为小部件实现了 QAccessibleTextInterface
。它在 Linux 下与 Orca 一起工作正常,但是当在 Windows 7 中与 NVDA 一起使用时,QAccessibleInterface::interface_cast()
请求错误的接口类型。使用 Orca,我收到了 QAccessible::TextInterface
的请求。在 NVDA 中,它总是 QAccessible::ValueInterface
.
AccessibleMyWidget
定义为:
class AccessibleMyWidget:
public QAccessibleWidget, public QAccessibleTextInterface {
public:
explicit AccessibleMyWidget(QWidget* w)
: QAccessibleWidget(w, QAccessible::EditableText)
{
Q_ASSERT(isValid());
}
void* interface_cast(QAccessible::InterfaceType t) override
{
if (t == QAccessible::TextInterface) {
// !!! This is never requested with NVDA !!!
return static_cast<QAccessibleTextInterface*>(this);
}
return QAccessibleWidget::interface_cast(t);
}
/*
* QAccessibleTextInterface implementation below this point.
*/
void addSelection(int startOffset, int endOffset) override;
QString attributes(int offset, int* startOffset,
int* endOffset) const override;
// etc.
};
使用 Linux 下的 Orca,一切似乎都按预期进行。我收到 interface_cast()
的 TextInterface
调用,之后调用 QAccessibleTextInterface
的各种函数。在 Linux 下使用 NVDA,我只得到 interface_cast()
对 ValueInterface
的调用,并且 QAccessibleTextInterface
函数的 none 被调用。这意味着 MyWidget
是完全不可访问的,除非我覆盖 QAccessibleWidget::text()
并且只是 return 所有文本作为一个字符串,这意味着没有光标导航,没有选择支持......它基本上变成了一个QLabel
此时,但有大量文本,因此很难使用。
我在这里错过了什么?
好吧,一位 NVDA 开发人员帮助我找到了这个问题。这是因为 Qt 的 MinGW 版本禁用了 IAccessible2,而是使用 MSAA(Microsoft Active Accessibility),它不支持任何这些接口。 IA2需要COM,而MinGW不支持。
所以我必须从 GCC/MinGW 切换到 MSVC 才能在 Windows 上完成这项工作。太糟糕了,在可预见的未来,这实际上不是一个选择:-/
2020 年更新:
从那以后,这已得到修复。不确定确切时间,但当前的 mingw Qt 构建现在支持此功能。
我正在使用 Qt 5.9.1。
我正在尝试使应用程序可通过屏幕阅读器访问。我有一个包含文本(很多)的自定义小部件(我们称它为 MyWidget
)。文本是使用 QPainter
绘制的,这就是为什么使用自定义小部件而不是 QTextBrowser
.
我在派生自 QAccessibleWidget
和 QAccessibleTextInterface
的 AccessibleMyWidget
class 中为小部件实现了 QAccessibleTextInterface
。它在 Linux 下与 Orca 一起工作正常,但是当在 Windows 7 中与 NVDA 一起使用时,QAccessibleInterface::interface_cast()
请求错误的接口类型。使用 Orca,我收到了 QAccessible::TextInterface
的请求。在 NVDA 中,它总是 QAccessible::ValueInterface
.
AccessibleMyWidget
定义为:
class AccessibleMyWidget:
public QAccessibleWidget, public QAccessibleTextInterface {
public:
explicit AccessibleMyWidget(QWidget* w)
: QAccessibleWidget(w, QAccessible::EditableText)
{
Q_ASSERT(isValid());
}
void* interface_cast(QAccessible::InterfaceType t) override
{
if (t == QAccessible::TextInterface) {
// !!! This is never requested with NVDA !!!
return static_cast<QAccessibleTextInterface*>(this);
}
return QAccessibleWidget::interface_cast(t);
}
/*
* QAccessibleTextInterface implementation below this point.
*/
void addSelection(int startOffset, int endOffset) override;
QString attributes(int offset, int* startOffset,
int* endOffset) const override;
// etc.
};
使用 Linux 下的 Orca,一切似乎都按预期进行。我收到 interface_cast()
的 TextInterface
调用,之后调用 QAccessibleTextInterface
的各种函数。在 Linux 下使用 NVDA,我只得到 interface_cast()
对 ValueInterface
的调用,并且 QAccessibleTextInterface
函数的 none 被调用。这意味着 MyWidget
是完全不可访问的,除非我覆盖 QAccessibleWidget::text()
并且只是 return 所有文本作为一个字符串,这意味着没有光标导航,没有选择支持......它基本上变成了一个QLabel
此时,但有大量文本,因此很难使用。
我在这里错过了什么?
好吧,一位 NVDA 开发人员帮助我找到了这个问题。这是因为 Qt 的 MinGW 版本禁用了 IAccessible2,而是使用 MSAA(Microsoft Active Accessibility),它不支持任何这些接口。 IA2需要COM,而MinGW不支持。
所以我必须从 GCC/MinGW 切换到 MSVC 才能在 Windows 上完成这项工作。太糟糕了,在可预见的未来,这实际上不是一个选择:-/
2020 年更新:
从那以后,这已得到修复。不确定确切时间,但当前的 mingw Qt 构建现在支持此功能。