Gio UI - GUI multiplateforme pour Go
(gioui.org)- Il s’agit d’une bibliothèque qui permet aux développeurs Go de créer des GUI en mode immédiat ciblant plusieurs systèmes d’exploitation ainsi que WebAssembly
- Elle prend en charge Linux, macOS, Windows, Android, iOS, FreeBSD, OpenBSD et WebAssembly, avec une large couverture de plateformes
- Sa conception vise à réduire les dépendances et s’appuie sur les bibliothèques de plateforme pour la gestion des fenêtres, les entrées et le rendu GPU
- Le rendu inclut le moteur de rendu vectoriel Pathfinder basé sur OpenGL ES et Direct3D 11, avec une transition en cours vers un moteur à compute shaders fondé sur piet-gpu
- Le texte et les formes sont rendus sous forme de contours plutôt que précalculés en textures, ce qui permet les animations, le dessin avec transformations et l’indépendance vis-à-vis de la résolution en pixels
Objectif et périmètre de prise en charge de Gio
- Gio est une bibliothèque destinée à créer en Go des GUI efficaces, fluides et portables
- Les plateformes prises en charge sont Linux, macOS, Windows, Android, iOS, FreeBSD, OpenBSD et WebAssembly
- Une démo WebAssembly rapide est disponible ; pour l’exécuter, un navigateur compatible WebAssembly est nécessaire
- Le code source d’exemple est disponible dans le projet Kitchen
Installation et parcours d’apprentissage
- Gio est conçu avec l’objectif de limiter les dépendances
- La documentation d’installation propre à chaque plateforme permet de vérifier les dépendances nécessaires
- Après l’installation, on peut commencer avec la documentation Learn et Hello World
- La vitrine comprend notamment godcr, Tailscale, gotraceui, Sointu et Protonet
Technologies de rendu
- Gio combine la flexibilité du paradigme graphique en mode immédiat avec les technologies graphiques 2D modernes
- Le moteur de rendu vectoriel est basé sur le projet Pathfinder et implémenté sur OpenGL ES et Direct3D 11
- Le moteur évolue vers un rendu à base de compute shaders plus efficace, construit sur piet-gpu
- Le texte et les formes ne sont pas précuits sous forme d’images de texture, mais rendus uniquement à partir de contours
- Cela permet des animations efficaces
- Cela convient au dessin transformé
- Cela permet de conserver l’indépendance vis-à-vis de la résolution en pixels
Modèle de financement
- Le développement de Gio est financé par des soutiens
- Si le projet vous est utile, vous pouvez envisager de soutenir le projet Gio sur OpenCollective ou de faire un don directement au développeur
1 commentaires
Avis Hacker News
Après l’avoir utilisé en pratique, il m’a semblé impossible de créer avec ça une application complexe sérieuse
Il manque des composants fournis par défaut sur d’autres plateformes, comme la vidéo, les cartes ou le texte riche, et il n’existe pas de voie claire et simple pour les ajouter soi-même
L’API casse tous les quelques mois, et il n’y a pas non plus de moyen d’appliquer des thèmes
Les graphismes en mode immédiat sont agréables jusqu’au moment où il faut gérer un état complexe ; à partir de là, on finit par devoir implémenter soi-même un mode conservé, ce qui ramène un problème résolu depuis longtemps
Même le moteur de rendu sophistiqué basé sur
piet-gpu, qui ne prend en entrée que des points de contrôle de courbes de Bézier et tesselle tout, est élégant conceptuellement, mais pour dessiner un vrai cercle, on dépend en pratique d’une approximation avec quatre courbes de BézierWasm ressemble davantage à une preuve de concept qu’une équipe de compilation devrait encore peaufiner pendant des années pour atteindre un niveau produit ; globalement, ça paraît correct pour un développeur Go qui veut créer une UI simple avec des listes et des champs de saisie
Il y a aussi un thème Material Design, ainsi que des modes clair/sombre
Un bon exemple d’application gioui avec mode clair/sombre et thèmes personnalisés est https://github.com/chapar-rest/chapar
Sur Mac ou Windows,
go run .suffitLe crénage du texte, le texte suivant un arc, ainsi que le RTL/LTR sont également possibles grâce à
github.com/go-text/typesettingOn trouve aussi sur GitHub des widgets complexes comme des sélecteurs de calendrier ou des diagrammes, mais il manque un effort pour les rassembler
Si ces éléments étaient réunis, cela donnerait sans doute beaucoup plus envie à davantage de développeurs de s’y mettre
Il ne semble pas y avoir de culture accordant de l’importance au fait de ne pas casser le code des utilisateurs
Les deux sont désormais stables et disposent d’un ensemble de contrôles et de bibliothèques relativement riche
Sur le Web, cela semble tout rendre dans un canvas, comme Flutter, mais cette approche est connue pour poser des problèmes d’accessibilité et de ressenti natif
On ne peut pas passer d’un bouton radio à l’autre avec Tab, sur macOS
CMD+Ane sélectionne pas tout le contenu d’un champ texte alors queCTRL+Ale faitCela semble possible, mais représenterait probablement pas mal de travail
C’est un peu hors sujet, mais je me demande quelle est aujourd’hui la meilleure façon de créer des apps mobiles et web multiplateformes
Que l’on partage à la fois la logique métier et l’UI, ou seulement la logique métier
J’ai hésité entre des options comme gomobile, Rust ou TypeScript
À une époque, TypeScript me semblait être la technologie la plus portable et je voulais l’utiliser pour toute la logique métier, mais j’ai compris qu’il n’existait pas vraiment de bonne façon de faire tourner JavaScript sur iOS avec des performances correctes
Si cela vous convient d’écrire l’UI en natif et de ne partager que la logique métier, Kotlin est aussi une option : https://kotlinlang.org/docs/multiplatform.html#kotlin-multip...
Avec Compose, on peut aussi créer l’UI en Kotlin : https://www.jetbrains.com/lp/compose-multiplatform/
Mais la prise en charge d’iOS est encore en alpha et le web est « experimental » ; donc si vous ne voulez pas vous retrouver à devoir modifier votre code au fil de l’évolution du framework, Flutter, déjà assez stable sur toutes les plateformes, est le bon choix
Si vous connaissez déjà TypeScript et React, React Native peut aussi être envisagé, mais il est difficile de garantir les performances sur iOS ou ailleurs : https://reactnative.dev/
J’ai vu trop de frameworks promettre de tout résoudre sans tenir leurs promesses
Au début, on démarre plus vite, mais très vite on se retrouve à patcher des bibliothèques cœur après une mise à jour d’OS pour rapprocher les FPS du natif ou mieux imiter les animations système
On ne gagne du temps que lorsqu’on ne peaufine pas l’UI
La logique cœur peut être partagée
J’utilise gomobile et je l’aime globalement bien, mais son overhead d’exécution est de 3 Mo, donc ce n’est pas adapté au web
Kotlin Multiplatform semblait prometteur, mais il manquait des bibliothèques de base et, comme elles existent déjà pour Kotlin Android, peu de gens semblaient créer leurs équivalents multiplateformes
Rust et la couche de bindings de Mozilla ont aussi l’air intéressants, mais je ne les ai pas encore essayés
Flutter n’est pas mauvais, mais sur le web il rend dans un canvas, ce qui est médiocre en termes de feeling et d’accessibilité
Sur iOS aussi, même après l’introduction du moteur de rendu Impeller, il reste des problèmes de latence
Le client Bluesky montre de bonnes performances sur l’ensemble des plateformes prises en charge, avec une base de code unique
https://github.com/bluesky-social/social-app
C’est open source et cela cible Android, iOS, Windows, Mac et Linux : https://platform.uno/platforms/
Il utilise C# et implémente automatiquement les vues et contrôles avec le framework UI natif de chaque plateforme
Le support des IDE comme Visual Studio, VS Code et Rider est bon, sans être limité à ces outils
Il existe aussi un plugin Figma pour la collaboration design
Je ne sais pas si c’est aussi un bon outil pour des produits grand public
Pour notre usage, il convient très bien : ce sont surtout des outils destinés à des techniciens de centrales solaires, et utiliser du TypeScript multiplateforme dans des conditions Internet difficiles devenait trop lourd pour une petite équipe
Je développe une app de streaming avec gioui, et c’est très facile ; les mises à jour se passent toujours sans douleur
Parce que c’est du Go et que les développeurs principaux prennent les changements assez au sérieux
Quand j’ai besoin d’une GUI web, j’utilise ce système de plugins gioui : https://github.com/gioui-plugins/gio-plugins
C’est étonnant de voir que WebView fonctionne sur le web, le desktop et le mobile
Les deep links fonctionnent aussi : si l’on envoie un lien par e-mail ou via une notification Monike, l’app de l’utilisateur s’ouvre exactement au bon endroit dans la GUI
Il y a aussi les notifications et les extensions de partage pour tous les OS, donc je trouve que c’est vraiment proche d’un système complet
Je suis d’accord sur le fait qu’il est difficile de prendre en charge tous les OS, mais dans le monde actuel la diversité est la norme
J’aime le fait de pouvoir faire tout cela uniquement en Go, sans passer d’une technologie à l’autre
J’écris toujours le backend Go pour qu’il fonctionne à la fois avec gio et avec HTML
Si j’ai besoin de SEO ou de lecture vidéo, je le gère dans WebView, et le côté web de gio peut aussi satisfaire le SEO de Google
Je mets du Markdown dans Hugo pour que Google SEO puisse le voir
Du point de vue d’un débutant en Go, cette partie de la documentation m’intrigue
La raison pour laquelle on utilise
op.ColorOp{Color: red}.Add(ops)au lieu deops.Add(ColorOp{Color: red})serait d’éviter les allocations à l’appel, en faisant en sorte que la méthodeAddne prenne pas d’argument de type interface, et c’est présenté comme essentiel dans la conception « zero allocation » de GioJ’aimerais comprendre pourquoi une allocation se produit, ce qui est alloué, et comment elle est économisée
Quand une fonction prend un argument de type interface et qu’on lui passe une structure pure, Go crée un wrapper autour ; c’est l’allocation dont parle la citation
Ce wrapper est une paire de pointeurs composée d’un pointeur de type/vtable et d’un pointeur vers les données de la structure
Cela permet l’inférence de type à l’exécution et l’extension implicite des interfaces
Autrement dit, pour implémenter une interface, il suffit d’implémenter ses méthodes, sans avoir à déclarer explicitement le type comme dans
ByteReader extends ReaderComme ce coût n’est payé qu’à l’utilisation, beaucoup de chemins rapides essaient autant que possible de n’utiliser que des structures
v := interfaceType(concreteTypeValue), à bas niveau il se passe à peu près cecidataPtr := &concreteTypeValue,typePtr := typeData[concreteType](), puis création d’une valeur d’interface contenant le pointeur de données et le pointeur de typeIci, la première ligne correspond à l’allocation, car d’après la règle dont je me souviens, en Go les pointeurs ne pointent pas vers des valeurs sur la pile, donc
concreteTypeValuedoit être alloué sur le tasLa règle selon laquelle les pointeurs ne pointent pas vers la pile facilite la croissance dynamique des piles de goroutines
Voir https://go.dev/doc/faq#stack_or_heap
ColorOp{Color: red}doit être boxé et alloué sur le tasParce que
ops.Addreçoit généralement un pointeur « large » vers une valeur qui implémente une certaine interface, plutôt qu’une valeur de type concretop.ColorOp{Color: red}.Add(ops)se lit bizarrementPour moi, ça se lit comme « ajouter
opsau résultat deop.ColorOp{Color: red}»Du coup, j’aurais envie de nommer la fonction
AddTo:op.ColorOp{Color: red}.AddTo(ops)Ce n’est toujours pas vraiment idiomatique, mais au moins ça signale que l’argument de la fonction est modifié
Il est intéressant de voir que, sur un PC assez banal avec Windows 10 et Chrome, la démo WASM de la première page ne rend que des carrés noirs aux endroits où il devrait y avoir du texte
Sur Chrome sur un téléphone Android, le rendu était correct
En plus, ça tournait extrêmement lentement
J’ai créé une petite application en Go avec Fyne, et je ne compte plus jamais l’utiliser
Gio comme Fyne sont très loin du niveau de finition et des fonctionnalités qu’offre Flutter
J’ai décidé de faire la logique principale en Golang et de l’envelopper dans une application Android, mais l’interface semblait sortie de 2003 et les possibilités de la corriger étaient limitées
On peut écrire toute la logique en Go et l’UI en HTML, avec ou sans framework web
C’est similaire à Electron, mais plus léger parce qu’il ne distribue pas Chrome avec l’application et utilise la vue web du système
[1] https://github.com/wailsapp/wails
J’aimerais bien que tu expliques comment tu l’as enveloppée dans une application Android
Pourquoi toutes ces GUI multiplateformes ont-elles l’air d’avoir été conçues il y a 50 ans ?
La démo ne fonctionne pas chez moi
Dans Chromium sur Win 11, je vois quelques boutons, mais la plupart des éléments sont entièrement noirs
Contrairement à Fyne, le fait que cette bibliothèque ait réussi mon premier test, le rendu de texte CJK, est bon signe
Fyne n’y arrive pas à moins qu’on lui fournisse une police personnalisée unique pour tout rendre
Bon courage pour trouver une seule police qui couvre correctement tous les systèmes d’écriture couramment utilisés dans le monde, sans parler des emoji
Donc dès qu’il y a le moindre contenu généré par les utilisateurs, contenu web ou possibilité de localisation, Fyne est immédiatement éliminé pour moi