A11y: query a11y bus address from X display

Attempt to get the accessibility bus address from the X display, to
match libatspi's behavior. This allows the accessibility bus to be
found when an application is running as root.

[ChangeLog][QtGui] Linux accessibility (using XCB) will now works for
applications launched as root

Done-with: Mike Gorse
Change-Id: I49a263571b328cbd1fd90cb7f5cb40919d2a4951
Task-number: QTBUG-43674
Reviewed-by: Laszlo Agocs <laszlo.agocs@theqtcompany.com>
Reviewed-by: Jørgen Lind <jorgen.lind@theqtcompany.com>
bb10
Frederik Gladhorn 2015-02-16 14:15:33 +01:00
parent 4dc459837b
commit d23562da1c
4 changed files with 56 additions and 2 deletions

View File

@ -42,6 +42,9 @@
#include <QDBusConnectionInterface>
#include "bus_interface.h"
#include <QtGui/qguiapplication.h>
#include <qplatformnativeinterface.h>
QT_BEGIN_NAMESPACE
QString A11Y_SERVICE = QStringLiteral("org.a11y.Bus");
@ -65,6 +68,29 @@ DBusConnection::DBusConnection(QObject *parent)
// If it is registered already, setup a11y right away
if (c.interface()->isServiceRegistered(A11Y_SERVICE))
serviceRegistered();
// In addition try if there is an xatom exposing the bus address, this allows applications run as root to work
QString address = getAddressFromXCB();
if (!address.isEmpty()) {
m_enabled = true;
connectA11yBus(address);
}
}
QString DBusConnection::getAddressFromXCB()
{
QGuiApplication *app = qobject_cast<QGuiApplication *>(QCoreApplication::instance());
if (!app)
return QString();
QPlatformNativeInterface *platformNativeInterface = app->platformNativeInterface();
QByteArray *addressByteArray = reinterpret_cast<QByteArray*>(
platformNativeInterface->nativeResourceForIntegration(QByteArrayLiteral("AtspiBus")));
if (addressByteArray) {
QString address = QString::fromLatin1(*addressByteArray);
delete addressByteArray;
return address;
}
return QString();
}
// We have the a11y registry on the session bus.

View File

@ -68,6 +68,7 @@ Q_SIGNALS:
void enabledChanged(bool enabled);
private Q_SLOTS:
QString getAddressFromXCB();
void serviceRegistered();
void serviceUnregistered();
void connectA11yBus(const QString &address);

View File

@ -77,7 +77,8 @@ static int resourceType(const QByteArray &key)
QByteArrayLiteral("gettimestamp"), QByteArrayLiteral("x11screen"),
QByteArrayLiteral("rootwindow"),
QByteArrayLiteral("subpixeltype"), QByteArrayLiteral("antialiasingEnabled"),
QByteArrayLiteral("nofonthinting")
QByteArrayLiteral("nofonthinting"),
QByteArrayLiteral("atspibus")
};
const QByteArray *end = names + sizeof(names) / sizeof(names[0]);
const QByteArray *result = std::find(names, end, key);
@ -175,6 +176,9 @@ void *QXcbNativeInterface::nativeResourceForIntegration(const QByteArray &resour
case Display:
result = display();
break;
case AtspiBus:
result = atspiBus();
break;
default:
break;
}
@ -402,6 +406,27 @@ void *QXcbNativeInterface::display()
#endif
}
void *QXcbNativeInterface::atspiBus()
{
QXcbIntegration *integration = static_cast<QXcbIntegration *>(QGuiApplicationPrivate::platformIntegration());
QXcbConnection *defaultConnection = integration->defaultConnection();
if (defaultConnection) {
xcb_atom_t atspiBusAtom = defaultConnection->internAtom("AT_SPI_BUS");
xcb_get_property_cookie_t cookie = Q_XCB_CALL(xcb_get_property(defaultConnection->xcb_connection(), false,
defaultConnection->rootWindow(),
atspiBusAtom,
XCB_ATOM_STRING, 0, 128));
xcb_get_property_reply_t *reply = Q_XCB_CALL(xcb_get_property_reply(defaultConnection->xcb_connection(), cookie, 0));
Q_ASSERT(!reply->bytes_after);
char *data = (char *)xcb_get_property_value(reply);
int length = xcb_get_property_value_length(reply);
QByteArray *busAddress = new QByteArray(data, length);
free(reply);
return busAddress;
}
return 0;
}
void QXcbNativeInterface::setAppTime(QScreen* screen, xcb_timestamp_t time)
{
static_cast<QXcbScreen *>(screen->handle())->connection()->setTime(time);

View File

@ -67,7 +67,8 @@ public:
RootWindow,
ScreenSubpixelType,
ScreenAntialiasingEnabled,
NoFontHinting
NoFontHinting,
AtspiBus
};
QXcbNativeInterface();
@ -98,6 +99,7 @@ public:
void *x11Screen();
void *rootWindow();
void *display();
void *atspiBus();
static void setStartupId(const char *);
static void setAppTime(QScreen *screen, xcb_timestamp_t time);
static void setAppUserTime(QScreen *screen, xcb_timestamp_t time);