Android
Android ist die einzige Plattform, auf der ein CGO-freier Prozess kein Fenster besitzen kann: Jeder Weg zu einer zeichenbaren Oberfläche führt über JNI, und JNI braucht cgo. Es gibt kein Wire-Protokoll, das man stattdessen sprechen könnte, so wie X11 und Wayland eines haben.
Deshalb besteht go-widgets/android aus zwei
Prozessen:
Java-Host (host/) | besitzt die Activity, die SurfaceView, Touch, Tasten und den Lebenszyklus. Überträgt Pixel per Blit; weiß nichts über Widgets. |
Go-Anwendung (cmd/gwapp) | ein gewöhnliches CGO_ENABLED=0 GOOS=android-Executable. Besitzt Layout, Widgets, Theme, Hit-Testing und Fokus, unverändert gegenüber jedem anderen Back-End. |
Der Java-Host steht dort, wo unter Linux der X-Server steht. Pixel reisen durch
ein memfd, das die Anwendung anlegt und dem Host über den Socket übergibt;
die Go-Seite schreibt RGBA_8888, was Byte für Byte Androids ARGB_8888 entspricht, sodass
der Blit eine Kopie ohne Umwandlung ist, und zwar nur des geschädigten Rechtecks. Eingaben,
Insets, IME-Text und der Barrierefreiheitsbaum gehen über ein gerahmtes Protokoll über einen
abstrakten LocalSocket.
c, err := android.Dial("my app", nil) // nil theme: toolkit.DefaultDark()
if errors.Is(err, android.ErrUnsupported) {
return nil // not under a host
}
defer c.Close()
return c.Run(myWidgetTree())Client erfüllt das Backend von window, sodass eine Anwendung zwischen
Android und den Desktop-Back-Ends wechselt, ohne eine Zeile oberhalb des Fensters zu ändern –
und window.Open
wählt es von selbst, wenn der Socket des Hosts vorhanden ist.
Nur arm64
android/arm64 ist das einzige Android-Ziel, das Go ohne cgo linkt; arm,
amd64 und 386 erfordern externes Linken. Die CI prüft beide Hälften – das eine Ziel,
das baut, und die drei, die es nicht tun –, sodass der Build es meldet, sobald Go die Einschränkung aufhebt.
Barrierefreiheit
Ein Screenreader würde die SurfaceView als ein einziges undurchsichtiges Rechteck sehen. Der Host
gibt ihm stattdessen eine virtuelle View-Hierarchie: einen Knoten pro zugänglichem Widget,
mit der android.widget.*-Klasse, nach der Android seine Ansagen auswählt, dem
Text, den Grenzen und einer Aktivierungsaktion. Der Baum wird abgeholt, wenn
etwas ihn liest, nie gepusht, sodass eine App ohne angeschlossenen Barrierefreiheitsdienst
nie einen aufbaut. Eine Aktivierung kommt als gewöhnlicher Klick in der
Mitte des Elements zurück, über denselben Code, den eine Berührung nimmt.
Touch und Animation
Jede Touch-Abtastung erreicht den Baum als Touch-Ereignis und dann als Maus-Ereignis: das erste für gestenfähige Widgets, das zweite für die vielen, die nur auf Klicks hören. Animierte Widgets laufen auf einer Frame-Schleife weiter, die startet, wenn etwas zu animieren beginnt, und stoppt, wenn nichts mehr animiert.
Erstellt am von tannevaled
Geändert am von tannevaled