- Libmui est une bibliothèque d’interface qui reproduit une grande partie de l’API « Toolbox » du Macintosh Classic ; ce n’est pas une implémentation complète, mais elle fournit les fonctions nécessaires à l’émulateur MII Apple //e et à quelques applications simples
- Le projet a commencé comme bibliothèque UI pour MII, avec pour objectif une interface disposée manuellement, plutôt qu’un système lourd en dépendances ou des menus de type jeu « flèches + Entrée + Échap »
- Le rendu consiste à dessiner dans un buffer ARGB, puis à le copier vers une texture OpenGL ou un pixmap partagé X11/XCB, tout en suivant les invalid regions pour ne redessiner que les zones nécessaires
- Contrairement à la Toolbox Macintosh d’origine, l’API fonctionne de manière asynchrone et basée sur des callbacks : quand l’état change, l’UI se redessine au moment opportun et les événements sont transmis par callback plutôt que par polling
- Elle propose Window, Menu, Control, List, Alert et Standard File, mais n’inclut pas le zoom, le redimensionnement, la boîte de dialogue Save, le dark mode, les thèmes, Wayland, GTK/QT/SDL ni de bindings Rust/Go/Python
Ce que Libmui produit
- Libmui est une bibliothèque qui reproduit une grande partie de l’API « Toolbox » du Macintosh Classic
- Ce n’est pas une implémentation complète, mais elle inclut les éléments nécessaires à quelques applications simples et au MII Apple //e emulator
- Le point de départ a été le besoin d’une bibliothèque UI pour MII, avec peu de dépendances et une interface qui ne soit pas orientée vers une navigation de menus façon jeu
- Nuklear, une UI en immediate mode, a d’abord été essayé, mais son apparence ne convenait pas, les possibilités de personnalisation semblaient limitées, et le moteur de layout plaçait les éléments autrement que souhaité
- L’expérience d’une UI en immediate mode conservant son état interne via des hash, avec de possibles collisions causant de vrais problèmes de debug, a aussi joué dans ce choix
- L’objectif est une interface peaufinée à la main plutôt qu’une UI décidée automatiquement par un moteur de layout
Modèle de rendu et d’exécution
- Libmui dessine l’interface sur un « écran » constitué d’un buffer ARGB
- Dans MII, ce buffer est superposé comme texture OpenGL
- La démo playground du dossier example le copie dans une fenêtre X11 via un pixmap partagé XCB, et cela fonctionne aussi sur un X11 distant
- Comme sur les anciens OS, il suit les invalid regions et ne redessine que les zones nécessaires
- L’ensemble n’est pas redessiné à chaque fois, donc l’overdraw est très faible
- Pour dessiner vers un framebuffer 16 bits, il faut convertir directement depuis la sortie ARGB
- Comme seule la dirty region doit être convertie, la charge reste modérée
- Le rendu pourrait être vectorisé via un vertex buffer ou autre, mais l’approche actuelle est jugée suffisamment rapide et ne nécessite pas de revenir à un fonctionnement où tout est redessiné comme dans une UI en immediate mode
Différences avec la Toolbox Macintosh d’origine
- Le style visuel part de MacOS 8/9, mais sans les éléments en niveaux de gris ; l’auteur estime que l’apparence plus plate de System 7 a mieux vieilli, et s’oriente donc dans cette direction
- Les menus contextuels sont plus proches d’OS8, tandis que les scrollbars rappellent davantage GS/OS
- La grande différence de l’API est son fonctionnement entièrement asynchrone
- On ne peut pas, comme à l’origine, dessiner n’importe quand dans une window ou un GrafPort via une spinloop
- Quand l’état de l’UI change, l’interface se redessine elle-même au moment opportun
- La gestion des événements est basée sur des callbacks
- Il n’y a pas de polling pour savoir ce qui s’est passé dans l’UI
- Quand un élément de menu est cliqué ou qu’un raccourci clavier est utilisé, le callback d’action est invoqué
- La structure conceptuelle est plus simple que l’originale
- Tout est soit un
mui_window, soit unmui_control - Les windows, menubars et menus sont des
mui_window - Les titres de menus, éléments de menu, tous les éléments dans une window et les lignes de séparation sont des
mui_control
- Tout est soit un
Gestionnaires et contrôles fournis
-
Window Manager
- Prend en charge la création des fenêtres et le dessin à l’intérieur des fenêtres
- Gère jusqu’à 15 couches, le clipping, l’action BringToFront et le déplacement des fenêtres par glisser-déposer
- Le système de coordonnées reste limité à deux repères comme à l’origine : les screen coordinates et les window content coordinates
- Il gère une liste de rectangles invalides pour éviter de redessiner toute la fenêtre à chaque fois
- Le zoom et le redimensionnement sont en TODO
- Les transparent windows ne sont volontairement pas prises en charge
- Les fenêtres sont dessinées de haut en bas pour optimiser le clipping
- Gérer la transparence imposerait un dessin de bas en haut et obligerait à redessiner davantage de contenu
- En revanche, il est possible d’appliquer un alpha blend à l’ensemble de l’écran UI à l’endroit voulu
-
Menu Manager
- Gère la menubar, les menus, les coches et les raccourcis clavier
- Conçu pour ressembler à System 7/8 ou GS/OS
- Il y a des menus hiérarchiques, mais pas totalement identiques à l’original et encore perfectibles
- L’affichage et le défilement de très grands menus contextuels sont en TODO
- La prise en charge des sticky menus est à moitié implémentée, mais reste désactivée car le comportement n’est pas encore correct
-
Control Manager
- Prend en charge les boutons, cases à cocher, boutons radio, scrollbars verticales et zones de texte avec retour à la ligne
- Edit Field est en cours de développement et Slider manque encore
- Le prototype de contrôle d’édition de texte est correct pour la saisie sur une ligne, mais pas encore adapté aux zones de texte multiligne
-
List Manager
- Pour l’instant, il est surtout codé en dur pour afficher des noms de fichiers
- Il gère les arrow keys, page up/down et la molette de défilement
- Comme dans le MacOS d’origine, on peut retrouver l’élément voulu via la recherche typeahead
- La compression de police ou l’abréviation par points de suspension quand le texte d’un élément est trop long sont en TODO
-
Alerts et Standard File
- Alert fournit les boîtes de dialogue classiques Cancel + OK
- D’autres types d’alert sont en TODO
- Standard File fournit la boîte de dialogue classique d’ouverture de fichier
- Cette fonction faisait partie des objectifs majeurs du projet au départ
- La boîte de dialogue Save est en TODO
- Un menu contextuel supplémentaire permet d’afficher les répertoires récemment utilisés
- Sont pris en charge : arrow keys, page up/down et recherche de fichiers en typeahead
-
Resource Manager
- Il n’y a pas de Resource Manager
- L’auteur considère qu’un outil du type ResEdit serait nécessaire, et cela reste hors du périmètre actuel
- Une idée de format MessagePack pour les ressources existe, mais elle est laissée pour plus tard
Dépendances et build
- La seule dépendance externe est libpixman
- libpixman est une bibliothèque de traitement de pixels qui fournit des fonctions de region utiles pour le clipping
- Ce n’est pas aussi bon que les regions de QuickDraw, mais cela est jugé suffisant
- Certains composants sont aussi inclus dans les sources
- libcg : un petit moteur de rendu antialiasé, proche de cairo, composé de deux fichiers
- stb_truetype.h : utilisé pour charger les polices TrueType
stb_ttc.h: extension destb_truetype.hqui construit un dictionnaire de polices/glyphes, une table de hachage, des textures de police, etc.- Le code de géométrie 2D a plus de 25 ans et est aussi inclus dans libc3
- La compilation se fait via un Makefile simple : il suffit d’exécuter
makeà la racine - Pour compiler tests, démos et exemples, il faut
xcb,xcb-shm,xcb-randr,xkbcommon-x11 - Avec le pilote binaire Nvidia, pour que
mui_shellfonctionne, il faut ajouterOption "AllowSHMPixmaps" "1"dans la sectionDevicede/etc/X11/xorg.conf
Utilisation et workflow de développement
- Pour démarrer, il est recommandé de modifier
mui_shell.cetmui_widgets_demo.c ui_mui_shellchargemui_widgets_demo.socomme plugin et le recharge automatiquement lorsqu’il détecte des changements- Quand
mui_widgets_demo.cest modifié, il est relancé après rechargement, ce qui permet de créer rapidement de nouvelles boîtes de dialogue - Exécuter
make watchdans le répertoirelibmuipermet de recompiler automatiquement la bibliothèque etmui_shellà chaque changement - Avec l’auto-save de l’éditeur, cela permet un workflow où l’on modifie, compile et exécute en continu
Ce qui n’est explicitement pas fourni
- pas de dark mode
- pas de prise en charge des thèmes
- pas de transparent windows ni d’effet cube
- les sticky menus ne sont pas activés actuellement
- n’utilise pas
cmake,meson,ninjani autotools - pas de bindings pour Rust, Go, Python ou autres langages
- n’utilise pas de framework comme GTK ou QT
- n’utilise pas SDL
- pas de prise en charge de Wayland
1 commentaires
Avis de Hacker News
À ce sujet, il existe une police TrueType dans le domaine public qui reproduit assez bien la police système Chicago d’origine : https://fontlibrary.org/en/font/chicagoflf
Charcoal, utilisée à partir de System 8.x, est beaucoup moins connue et, personnellement, je la considère comme une nette amélioration
Cela dit, passer la bibliothèque à Chicago est en fait assez simple. En dehors de la copie mentionnée, une version TTF « plain » de la Chicago originale circule quelque part
Ensuite, il suffit de convertir le TTF en OTF avec l’outil en ligne de commande de FontForge : https://www.macintoshrepository.org/1682-mac-os-7-6-x
fontforge -script -c 'Open($1); Generate($2);' input_font.ttf output_font.otfVraiment superbe. Michel l’a créée pour son émulateur Apple II, et je m’en sers un peu comme une plaisanterie pour remplacer le frontend de l’émulateur Archimedes
C’est encore très précoce, mais si j’arrive à comprendre l’API, c’est forcément qu’elle est correcte :)
Cela dit, j’ai quand même de l’affection pour l’interface classique du Mac
J’ai bien aimé le rastériseur graphique 2D à double en-tête utilisé par ce projet : https://github.com/xboot/libcg
C’est toujours étonnant de voir qu’on peut créer des logiciels puissants avec aussi peu de dépendances
Est-ce vraiment si difficile de créer une bibliothèque d’UI propre et puissante qui puisse servir d’alternative à Electron ?
Impressionnant. Sous licence MIT et écrit en C ! En ajoutant un shim pour l’API AppKit, cela pourrait peut-être même rivaliser avec GNUstep
C’est joli. J’aimerais pouvoir transformer toute mon interface macOS comme ça
Bon projet. J’aimais vraiment l’ancienne interface classique du Mac
Les exemples ont tous l’air excellents, et le code de démonstration des widgets donne l’impression que c’est aussi facile à utiliser
Vraiment génial. Je me demande quel effort il faudrait pour lire les fichiers de ressources (.rsrc) du resource fork et construire l’UI à partir de ça
Si c’était possible, on pourrait utiliser ResEdit :-)