[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gambas-bugtracker] Bug #3188: Making Gambas GTK apps testable via AT-SPI: patch to add accessible names for Label/ComboBox/buttons
[Thread Prev] | [Thread Next]
- Subject: [Gambas-bugtracker] Bug #3188: Making Gambas GTK apps testable via AT-SPI: patch to add accessible names for Label/ComboBox/buttons
- From: <bugtracker@xxxxxxxxxxxxxx>
- Date: Tue, 23 Jun 2026 13:09:25 GMT
- To: arothe@xxxxxxxxx,bugtracker@xxxxxxxxxxxxxxxxxxxxxx
http://gambaswiki.org/bugtracker/edit?object=BUG.3188&from=L21haW4- André ROTHE reported a new bug. Summary ------- Making Gambas GTK apps testable via AT-SPI: patch to add accessible names for Label/ComboBox/buttons Type : Request Priority : Medium Gambas version : Master Product : GTK+3 component Description ----------- Hi, I'm using Gambas to build a complex application (a client UI for REST services), and I want to cover it with end-to-end (E2E) tests. The tests are written by Claude Code, which is surprisingly good at Gambas. The idea is to let Claude drive the running Gambas application — following my instructions — to test functionality. This works because a lot of information about the GTK widgets is available through the AT-SPI accessibility tree (the same one screen readers use, exposed via ATK). However, some custom-drawn widgets expose an empty AT-SPI name/description, so Claude had to fall back to locating them by pixel geometry. To avoid that brittle workaround, I patched my local Gambas to fill in those missing names and descriptions. The widgets I found so far are Label, ComboBox (read-only) and the push/toggle/tool buttons — there may well be more. I'm attaching the patch and a demo app (UI in Gambas, tests in Python) so you can check the changes. It's quite cool to watch an automated Gambas application run on your desktop :-) About the demo: test_widgets.py compiles and starts the Gambas demo app, then selects some buttons etc. It builds on e2e_uidriver.py, which is almost generic (it works with any Gambas GTK2/GTK3 app) and provides the methods to find and operate widgets in the Gambas component tree. Claude Code can add new test steps on top of e2e_uidriver.py. How the patch works (for review): Since Gambas 3.16 many widgets in gb.gui.base (Label, TextLabel, ComboBox, …) are UserControls that paint their own text, so the underlying GTK widget has no GtkLabel child and ATK derives an empty accessible name. The same is true for the custom-drawn push/toggle/tool buttons in gb.gtk (their text goes through a GtkCellRendererText, not a label child). The patch fixes this in two layers: gb.gtk (C++): I added a hidden Control._AccessibleName property (CWidget.cpp) backed by a new gControl::setAccessibleName() (gcontrol.cpp/.h), which calls atk_object_set_name(gtk_widget_get_accessible(border), …). In gControl::setTooltip() I now also set the ATK description explicitly from the tooltip (markup-stripped via pango_parse_markup), because GTK only derives it lazily, so it reads empty/racy right after launch. In gButton::setText() the custom-drawn button branch now sets the ATK name from the plain (markup-stripped) text. gb.gui.base (Gambas): the self-painting widgets push their displayed text into that property — e.g. Label.class calls Me._AccessibleName = $sText whenever the text changes, and ComboBox.class publishes the selected value (so a read-only combo, whose value isn't shown in a child widget, becomes readable). The call is wrapped in Try, so on a toolkit that doesn't implement _AccessibleName it's simply a no-op. Because gb.gtk3/src/*.cpp are symlinks to gb.gtk/src/, the C++ part covers both GTK2 and GTK3. Qt is not covered — gb.qt* has no _AccessibleName, so there the Try does nothing; a QAccessible-based equivalent would be the analogous fix. All names/descriptions added are derived from text the user already set (Text/Caption, tooltip, selected value), so they should be correct by construction. These are the widgets I hit during testing; there are very likely more UserControl-based widgets that deserve the same one-line _AccessibleName treatment. Best regards, André System information ------------------ [System] Gambas=3.21.99 51912e1da (master) OperatingSystem=Linux Distribution=openSUSE Leap 16.0 Kernel=6.12.0-160000.32-default Architecture=x86_64 Cores=12 Memory=31712M Language=de_DE.utf8 Platform=x11 Desktop=MATE DesktopResolution=96 DesktopScale=7 WidgetTheme=green-submarine Font=Sans,10 DarkTheme=False [Programs] gcc=gcc (SUSE Linux) 15.2.0 git=git version 2.51.0 msgmerge=msgmerge (GNU gettext-tools) 0.22.5 pngquant=2.18.0 (January 2023) rpmbuild=RPM version 4.20.1 [Libraries] Cairo=libcairo.so.2.11804.4 Curl=libcurl.so.4.8.0 DBus=libdbus-1.so.3.32.4 GDK2=libgdk-x11-2.0.so.0.2400.33 GDK3=libgdk-3.so.0.2418.32 GStreamer=libgstreamer-1.0.so.0.2607.0 GTK+2=libgtk-x11-2.0.so.0.2400.33 GTK+3=libgtk-3.so.0.2418.32 OpenGL=libGL.so.1.7.0 Poppler=libpoppler.so.148.0.0 QT5=libQt5Core.so.5.15.17 QT6=libQt6Core.so.6.9.1 RSvg=librsvg-2.so.2.60.2 SDL=libSDL2-2.0.so.0.3000.7 SQLite3=libsqlite3.so.3.51.3 [Environment] AUDIODRIVER=pulseaudio CLUTTER_BACKEND=x11,* CONFIG_SITE=/usr/share/site/x86_64-pc-linux-gnu CPU=x86_64 CSHEDIT=emacs CVS_RSH=ssh DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus DEBUGINFOD_URLS=https://debuginfod.opensuse.org/ DESKTOP_SESSION=mate DISPLAY=:0 EDITOR=pluma FROM_HEADER= GB_GUI=gb.gtk3 GDMFLEXISERVER=/usr/libexec/lightdm/gdmflexiserver GDMSESSION=mate GDM_LANG=de_DE.utf8 GIO_LAUNCHED_DESKTOP_FILE_PID=2284193 GPG_TTY=kein Terminal GTK_IM_MODULE=ibus GTK_MODULES=canberra-gtk-module:canberra-gtk-module GTK_OVERLAY_SCROLLING=0 GUESTFISH_INIT=\e[1;34m GUESTFISH_OUTPUT=\e[0m GUESTFISH_PS1=\[\e[1;32m\]><fs>\[\e[0;31m\] GUESTFISH_RESTORE=\e[0m G_BROKEN_FILENAMES=1 G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-15,CP1252 HISTSIZE=1000 HOME=<home> HOST=<hostname> HOSTNAME=<hostname> HOSTTYPE=x86_64 INPUT_METHOD=ibus JAVA_BINDIR=/usr/lib64/jvm/java-21-openjdk-21/bin JAVA_HOME=/usr/lib64/jvm/java-21-openjdk-21 JDK_HOME=/usr/lib64/jvm/java-21-openjdk-21 JRE_HOME=/usr/lib64/jvm/java-21-openjdk-21 LANG=de_DE.utf8 LANGUAGE=de_DE.utf8 LD_LIBRARY_PATH=/usr/lib/oracle/21/client64/lib: LESS=-M -I -R LESSCLOSE=lessclose.sh %s %s LESSKEY=/usr/etc/lesskey.bin LESSOPEN=lessopen.sh %s LESS_ADVANCED_PREPROCESSOR=no LOGNAME=<user> MACHTYPE=x86_64-suse-linux MAIL=/var/mail/<user> MANPATH=<home>/.local/share/man:/usr/local/man:/usr/local/share/man:/usr/share/man MANPATHISSET=yes MATE_DESKTOP_SESSION_ID=this-is-deprecated MINICOM=-c on MORE=-sl MOZ_GMP_PATH=/usr/lib64/mozilla/plugins/gmp-gmpopenh264/system-installed MULE_HOME=/opt/mule-standalone-4.6.0 NLS_LANG=GERMAN_GERMANY.UTF8 OLDPWD=<home> OSTYPE=linux PAGER=less PATH=<home>/.npm-global/bin:<home>/.local/bin:<home>/bin:/usr/local/bin:/usr/bin:/bin:<home>/.dotnet/tools:/snap/bin:/var/lib/snapd/snap/bin PROFILEREAD=true PWD=<home> QEMU_AUDIO_DRV=pa QT4_IM_MODULE=xim QT_FONT_DPI=96 QT_IM_MODULE=ibus QT_IM_SWITCHER=imsw-multi QT_LOGGING_RULES=*.debug=false QT_QPA_PLATFORMTHEME=gtk2 QT_SCALE_FACTOR=1 SDK_HOME=/usr/lib64/jvm/java-21-openjdk-21 SESSION_MANAGER=local/<hostname>:@/tmp/.ICE-unix/3010,unix/<hostname>:/tmp/.ICE-unix/3010 SHELL=/bin/bash SHLVL=0 SQLPATH=/usr/lib/oracle/21/client64/lib: SSH_AGENT_PID=3103 SSH_ASKPASS=/usr/libexec/ssh/ssh-askpass SSH_AUTH_SOCK=/run/user/1000/keyring/ssh TERM=xterm TNS_ADMIN=/opt/iclient TZ=:/etc/localtime USER=<user> VDPAU_DRIVER=va_gl VENDOR=suse WINDOWMANAGER=mate-session XAUTHLOCALHOSTNAME=<hostname> XAUTHORITY=<home>/.Xauthority XDG_ACTIVATION_TOKEN=mate-panel-3172-<hostname>-gambas3-8_TIME2955605005 XDG_CACHE_HOME=<home>/.cache XDG_CONFIG_DIRS=/etc/xdg:/usr/local/etc/xdg:/usr/etc/xdg XDG_CONFIG_HOME=<home>/.config XDG_CURRENT_DESKTOP=MATE XDG_DATA_DIRS=<home>/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/share/mate:/usr/local/share/:/usr/share/:/var/lib/snapd/desktop XDG_DATA_HOME=<home>/.local/share XDG_GREETER_DATA_DIR=/var/lib/lightdm-data/<user> XDG_RUNTIME_DIR=/run/user/1000 XDG_SEAT=seat0 XDG_SEAT_PATH=/org/freedesktop/DisplayManager/Seat0 XDG_SESSION_CLASS=user XDG_SESSION_DESKTOP=mate XDG_SESSION_ID=3 XDG_SESSION_PATH=/org/freedesktop/DisplayManager/Session0 XDG_SESSION_TYPE=x11 XDG_STATE_HOME=<home>/.local/state XDG_VTNR=7 XKEYSYMDB=/usr/X11R6/lib/X11/XKeysymDB XMODIFIERS=@im=ibus XNLSPATH=/usr/share/X11/nls XSESSION_IS_UP=yes ----[ Gambas bugtracker-list is hosted by https://www.hostsharing.net ]----
| [Gambas-bugtracker] Bug #3188: Making Gambas GTK apps testable via AT-SPI: patch to add accessible names for Label/ComboBox/buttons | <bugtracker@xxxxxxxxxxxxxx> |