Files
cthulhu/tests/atspi_refresh_signals.c

56 lines
2.6 KiB
C

// Copyright (c) 2026 Storm Dragon
// Authors: Storm Dragon, Angus Kola
// SPDX-License-Identifier: GPL-3.0-or-later
#include <atspi/atspi.h>
#include <dbus/dbus.h>
// Use GTK's actual accessibility connection, bypassing the ATK bridge's
// producer-side event compression. The reader must handle a provider which
// delivers every stale claim, as in the captured timeline refresh.
static void emit_event(DBusConnection *bus, const char *path, const char *member,
const char *detail, int detail1, const char *child) {
DBusMessage *message = dbus_message_new_signal(path, "org.a11y.atspi.Event.Object", member);
DBusMessageIter body, variant, reference, properties;
int zero = 0;
dbus_message_iter_init_append(message, &body);
dbus_message_iter_append_basic(&body, DBUS_TYPE_STRING, &detail);
dbus_message_iter_append_basic(&body, DBUS_TYPE_INT32, &detail1);
dbus_message_iter_append_basic(&body, DBUS_TYPE_INT32, &zero);
dbus_message_iter_open_container(&body, DBUS_TYPE_VARIANT, child != NULL ? "(so)" : "i", &variant);
if (child != NULL) {
const char *sender = dbus_bus_get_unique_name(bus);
dbus_message_iter_open_container(&variant, DBUS_TYPE_STRUCT, NULL, &reference);
dbus_message_iter_append_basic(&reference, DBUS_TYPE_STRING, &sender);
dbus_message_iter_append_basic(&reference, DBUS_TYPE_OBJECT_PATH, &child);
dbus_message_iter_close_container(&variant, &reference);
} else {
dbus_message_iter_append_basic(&variant, DBUS_TYPE_INT32, &zero);
}
dbus_message_iter_close_container(&body, &variant);
dbus_message_iter_open_container(&body, DBUS_TYPE_ARRAY, "{sv}", &properties);
dbus_message_iter_close_container(&body, &properties);
dbus_connection_send(bus, message, NULL);
dbus_message_unref(message);
}
const char *refresh_bus_name(void) {
return dbus_bus_get_unique_name(atspi_get_a11y_bus());
}
void emit_refresh(const char *tablePath, const char *cellPaths) {
DBusConnection *bus = atspi_get_a11y_bus();
gchar **paths = g_strsplit(cellPaths, ",", -1);
for (guint index = 0; paths[index] != NULL; index++) {
emit_event(bus, paths[index], "StateChanged", "defunct", 1, NULL);
}
for (guint index = 0; paths[index] != NULL; index++) {
emit_event(bus, paths[index], "StateChanged", "selected", 1, NULL);
emit_event(bus, tablePath, "SelectionChanged", "", 0, NULL);
emit_event(bus, paths[index], "StateChanged", "focused", 1, NULL);
emit_event(bus, tablePath, "ActiveDescendantChanged", "", 1, paths[index]);
}
g_strfreev(paths);
dbus_connection_flush(bus);
}