The Assistive Technology Service Provider Interface (AT-SPI) is a very nice infrastructure for querying information from a GNOME desktop. There are IDL bindings for it, but the most commonly used binding is cspi, a C library for accessing the AT-SPI.
Since I come from a Emacs-Lisp background, I really like the dynamic evaluation concept of Lisp and Scheme. Edit-Compile-Run is not what I particularily enjoy. So I decided to write a Scheme binding for AT-SPI, using Guile.
Here is a somewhat contrived example of a typical gspi usage session. It should help to get you started despite the lack of Scheme at-spi function documentation, and should also give you an idea what you can use gspi for.
Guile AT-SPI Version 0.0.2
gspi> (spi-init)
0
gspi> (define apps (applications))
gspi> apps
(#<Accessible 0x80e62a8, name="gnome-session", role=application> #<Accessible 0x80e6130, name="nautilus", role=application> #<Accessible 0x80e54b0, name="gnome-panel", role=application> #<Accessible 0x80e5eb8, name="mixer_applet2", role=application>)
gspi> (define nautilus (cadr apps))
gspi> (children nautilus)
(#<Accessible 0x80e6560, name="Desktop", role=frame>)
gspi> (find nautilus focused?)
(#<Accessible 0x80fc9f0, name="Start Here", role=unknown>)
gspi> (find nautilus (lambda (obj) (eq? (get-role obj) 'menu)))
(#<Accessible 0x80e8ad8, name="", role=menu>)
gspi> (define nautilus-menu (car (find nautilus (lambda (obj) (eq? (get-role obj) 'menu)))))
gspi> (children nautilus-menu)
()
gspi> nautilus-menu
#<Accessible 0x80e8ad8, name="", role=menu>
gspi> (next-child nautilus-menu)
#<Accessible 0x80e8960, name="", role=menu-item>
gspi> (next-child nautilus-menu 2)
#<Accessible 0x80e87e8, name="", role=menu>
gspi> (next-child nautilus-menu 3)
#<Accessible 0x80e8440, name="", role=menu>
gspi> (next-child nautilus-menu 4)
#f
gspi> (map get-name (find (desktop 0) (lambda (obj) (and (focusable? obj) (visible? obj)))))
("Start Here" "root's Home" "Trash" "Start Here" "" "Error" "Home Folder
View your home folder in the Nautilus file manager" "Terminal
Command line")
gspi> (map (lambda (obj) (list (get-layer obj) (get-extents obj)))
(toplevels))
((window (0 0 1024 768)) (window (0 740 1024 28)) (window (0 0 1024 24)))
gspi>
Example:
*GNOME desktop 0*.
Scheme filter: nil
--, Redraw
|-- gnome-session (GAIL V1.2.2 id=1)
+-- gnome-panel (GAIL V1.2.2 id=2)
+-- nautilus (GAIL V1.2.2 id=3)
--, gedit (GAIL V1.2.2 id=9)
--, frame Untitled 1 - gedit
--, filler
--, panel
| --, panel
| | --, panel
| | |-- unknown grip ()
| | --, menu-bar
| | +-- menu File (click=f;f;)
| | +-- menu Edit (click=e;e;)
| | +-- menu View (click=v;v;)
| | +-- menu Search (click=s;s;)
| | +-- menu Tools (click=t;t;)
| | +-- menu Documents (click=d;d;)
| | +-- menu Help (click=h;h;)
| | +-- menu Debug (click=d;d;)
| +-- panel
| +-- split-pane
+-- filler
This also creates the problem that the Emacs support library can not implement event handling currently, because it would need to launch a separate, second gspi process, which would leave me with the situation of having to deal with data in three different worlds, which does not appear to me as very useful.