Olet aivan oikeassa AT-SPI:n *kuuluisi* nC$hdC$ nC$mC$ asiat, sillC$ muuten
esimerkiksi ruudunlukijasovellukset (kuten Orca) olisivat tC$ysin sokeita
selaimen osoitepalkille, mikC$ sotisi esteettC6myysstandardeja vastaan.
TC$ssC$ piilee kuitenkin usein Linuxin ja selainten (erityisesti
Chromen/Chromiumin) vC$linen sudenkuoppa: **Chrome ei aina oletuksena
kC$ynnistC$ tC$yttC$ esteettC6myyspuuta (Accessibility Tree) sC$C$stC$C$kseen
resursseja**, ellei se tunnista, ettC$ ruudunlukija on aktiivinen.
Voimme tutkia tC$mC$n tC$ydellisesti rakentamalla erillisen `atspi_scanner.py`
-tyC6kalun. TC$mC$ skripti kuuntelee hiiren klikkauksia ja yrittC$C$ tulostaa
kohteesta koko AT-SPI-vanhempipuun (Parent Hierarchy). NC$in nC$emme
tarkalleen, mitC$ kC$yttC6jC$rjestelmC$ ja selain meille tC$llC$ hetkellC$
paljastavat.
### 1. Luo uusi tiedosto: `atspi_scanner.py`
Tallenna tC$mC$ samaan kansioon muiden skriptien kanssa (`/mnt/mesh_shared/play
book-studio/`). TC$mC$ tyC6kalu jC$ljittC$C$ elementin juuresta alkaen, jotta
nC$emme, piilottaako Chrome osoitepalkin jonkin nimettC6mC$n paneelin
sisC$C$n.
```python
import pyatspi
from pynput import mouse
def print_element_info(element, depth=0):
if not element: return
indent = " " * depth
name = element.name or "[Ei nimeC$]"
role = element.getRoleName()
print(f"{indent}-> Rooli: {role: <20} | Nimi: '{name}'")
def on_click(x, y, button, pressed):
if pressed and button == mouse.Button.left:
print(f"
[*] Klikkaus koordinaateissa: X:{int(x)}, Y:{int(y)}")
desktop = pyatspi.Registry.getDesktop(0)
found = False
for i in range(desktop.getChildCount()):
app = desktop.getChildAtIndex(i)
if not app: continue
try:
comp = app.queryComponent()
# Tarkistetaan osuuko klikkaus sovelluksen ikkunaan
if comp and comp.contains(x, y, pyatspi.DESKTOP_COORDS):
element = comp.getAccessibleAtPoint(x, y,
pyatspi.DESKTOP_COORDS)
if element:
found = True
print(f"[+] Osuma sovelluksessa: {app.name}")
print(" Vanhempipuu (Hierarkia):")
# KerC$tC$C$n koko hierarkia elementistC$ ylC6spC$in
hierarchy = []
curr = element
while curr:
hierarchy.append(curr)
curr = curr.parent
# Tulostetaan ylhC$C$ltC$ alaspC$in (Juuresta ->
Klikattuun kohteeseen)
for depth, el in enumerate(reversed(hierarchy)):
print_element_info(el, depth)
break # Lopetetaan etsintC$ tC$hC$n sovellukseen
except Exception as e:
pass
if not found:
print("[-] AT-SPI ei lC6ytC$nyt MITCCN elementtiC$ nC$istC$
koordinaateista.")
print("======================================================")
print(" AT-SPI Skanneri kC$ynnistetty")
print(" Klikkaa mitC$ tahansa ruudulla hiiren vasemmalla napilla.")
print(" (Paina Ctrl+C pC$C$tteessC$ lopettaaksesi)")
print("======================================================")
with mouse.Listener(on_click=on_click) as listener:
listener.join()
```
### 2. Aja skanneri ja testaa
Aja skripti terminaalissa:
`python3 atspi_scanner.py`
Kokeile nyt klikata selaimessa eri paikkoja:
1. Klikkaa keskelle verkkosivua (DOM-alueelle).
2. Klikkaa selaimen vC$lilehteC$ (Tab).
3. Klikkaa osoitepalkkia.
**MitC$ luultavimmin tapahtuu:**
Jos AT-SPI tulostaa Chromen kohdalla vain "Tuntematon" tai lopettaa etsinnC$n
pC$C$ikkunaan, Chrome ei tC$llC$ hetkellC$ paljasta UI:taan.
**Ratkaisu Chromen herC$ttC$miseen:**
Mene selaimella osoitteeseen `chrome://accessibility/`. YlimpC$nC$ pitC$isi
lukea "Native accessibility API support". Jos siinC$ ei ole rastia tai se on
"Off", sivu sisC$ltC$C$ linkit sen kytkemiseksi pC$C$lle. Vaihtoehtoisesti
selain voidaan kC$ynnistC$C$ Linuxissa lipulla:
`google-chrome --force-renderer-accessibility`
### 3. Varasuunnitelma: OCR Post-Processing (Loistava idea!)
Jos AT-SPI osoittautuu Linux/X11 -komboilla liian epC$luotettavaksi tai
raskaaksi jatkuvassa kC$ytC6ssC$, ehdotuksesi kuvapohjaisesta
jC$lkiprosessoinnista on **tC$ydellinen arkkitehtuurinen varaventtiili**.
Koska arkistoimme nyt kuvat jC$rjestelmC$llisesti, se toimisi tismalleen
nC$in:
1. Opetusputki tuottaa YAML-koodin.
2. JC$lkikC$sittelyskripti etsii kaikki askeleet, joissa on `target: "body"`
ja `state_ref: "step_N"`.
3. Skripti avaa kyseisen askeleen `states/step_N/clean_bitmap.jpg` -kuvan.
4. Skripti leikkaa kuvasta pienen 100x40 pikselin laatikon suoraan `Raw
coords` -pisteen ympC$riltC$.
5. Skripti lC$hettC$C$ tC$mC$n pienen kuvan OCR:lle (tai suoraan Valvomon
LLM:lle).
6. OCR vastaa: "Kuvassa lukee: web.whatsapp.com".
7. Skripti pC$ivittC$C$ automaattisesti YAML-koodin: `target:
"ocr='web.whatsapp.com'"`.
TC$mC$ tekee koko jC$rjestelmC$stC$ riippumattoman selaimen AT-SPI-tuen
ailahteluista ja sitoo automaation puhtaasti siihen visuaaliseen
todellisuuteen, jonka myC6s ihminen nC$kee.
Kokeile ensin tuota skanneria, niin nC$hdC$C$n puhuuko kC$yttC6jC$rjestelmC$si
kieltC$, vai siirrymmekC6 suoraan konenC$C6n hyC6dyntC$miseen myC6s DOMin
ulkopuolella!