Announce the initial row in unselected GTK menus

This commit is contained in:
ak47 committed 2026-11-10 21:26:17 -05:00
1 parent 090ac9dbeb
commit ae53f23c63
6 files changed
+190 -3

No files matched your search

+38
View File
@@ -219,6 +219,44 @@ AtspiAccessible *cthulhu_table_selected_child(AtspiAccessible *source) {
return child;
}
// GTK lists populated through stdin can have no selected row at focus time.
// Their first navigation starts at row zero. Present that initial row without
// selecting it or moving the application's cursor. Selection-change queries
// must continue to return only actual selections.
AtspiAccessible *cthulhu_table_focus_child(AtspiAccessible *source) {
AtspiAccessible *child = cthulhu_table_selected_child(source);
if (child != NULL) return child;
gchar *toolkit = atspi_accessible_get_toolkit_name(source, NULL);
gboolean gtk = g_ascii_strcasecmp(toolkit != NULL ? toolkit : "", "gtk") == 0;
g_free(toolkit);
if (!gtk) return NULL;
AtspiStateSet *states = atspi_accessible_get_state_set(source);
gboolean initial = states != NULL &&
atspi_state_set_contains(states, ATSPI_STATE_FOCUSED) &&
!atspi_state_set_contains(states, ATSPI_STATE_MULTISELECTABLE);
if (states != NULL) g_object_unref(states);
if (!initial) return NULL;
AtspiTable *table = atspi_accessible_get_table_iface(source);
if (table == NULL) return NULL;
GError *error = NULL;
gint selected = atspi_table_get_n_selected_rows(table, &error);
if (error == NULL && selected == 0 && atspi_table_get_n_rows(table, NULL) > 0 &&
atspi_table_get_n_columns(table, NULL) == 1) {
child = atspi_table_get_accessible_at(table, 0, 0, NULL);
if (child != NULL) {
states = atspi_accessible_get_state_set(child);
gboolean showing = states != NULL &&
atspi_state_set_contains(states, ATSPI_STATE_SHOWING) &&
!atspi_state_set_contains(states, ATSPI_STATE_DEFUNCT);
if (states != NULL) g_object_unref(states);
if (!showing) { g_object_unref(child); child = NULL; }
}
}
g_clear_error(&error);
g_object_unref(table);
return child;
}
// Resolve the focused descendant at a window-activation boundary. Providers
// such as Steam's Chromium UI can activate a frame without emitting a usable
// object-focus event. Keep the synchronous callback work bounded so a broken