2 pontos por GN⁺ 2024-04-02 | 1 comentários | Compartilhar no WhatsApp
  • Libmui é uma biblioteca de UI que replica boa parte da API “Toolbox” do Macintosh Classic; não é uma implementação completa, mas oferece os recursos necessários para o emulador MII Apple //e e para aplicativos simples
  • Começou como uma biblioteca de UI para o MII e busca uma UI posicionada manualmente, sem muitas dependências e sem menus com estilo de jogo baseados em “Arrow Keys + Return + Escape”
  • A renderização funciona desenhando em um buffer ARGB e depois copiando para uma textura OpenGL ou para um shared pixmap do X11/XCB, acompanhando regiões inválidas para redesenhar apenas o necessário
  • Diferentemente da Toolbox original do Macintosh, a API funciona de forma assíncrona e baseada em callbacks; ao mudar o estado, a UI se redesenha quando necessário, e os eventos são entregues por callback em vez de polling
  • Inclui recursos de Window, Menu, Control, List, Alert e Standard File, mas não oferece zooming, resizing, diálogo de Save, dark mode, themes, Wayland, GTK/QT/SDL nem bindings para Rust/Go/Python

O que a Libmui oferece

  • Libmui é uma biblioteca que replica grande parte da API “Toolbox” do Macintosh Classic
  • Não é uma implementação completa, mas inclui as partes necessárias para alguns aplicativos simples e para o emulador MII Apple //e
  • Ela surgiu da necessidade de uma biblioteca de UI para o MII, com poucas dependências e sem foco em uma navegação de menu com cara de jogo
  • Primeiro foi testada uma UI immediate mode com Nuklear, mas o visual não agradou, a personalização era limitada e o mecanismo de layout colocava elementos em posições diferentes das desejadas
  • Também pesou a experiência de que UIs immediate mode mantêm estado interno baseado em hash, e colisões de hash podem gerar problemas reais de depuração
  • O objetivo é chegar mais perto de uma UI refinada manualmente do que de uma UI decidida automaticamente por um mecanismo de layout

Modelo de renderização e funcionamento

  • A Libmui desenha a UI em uma “screen” formada por um buffer ARGB
    • No MII, esse buffer é sobreposto como uma textura OpenGL
    • A demo playground na pasta example copia o resultado para uma janela X11 usando XCB shared pixmap, e também funciona em X11 remoto
  • Como em sistemas antigos, ela acompanha a invalid region e redesenha só as partes necessárias
    • Não redesenha tudo a cada vez, então o overdraw é muito baixo
    • Para desenhar em um framebuffer de 16 bits, por exemplo, é preciso converter diretamente a partir da saída ARGB
    • Como só a dirty region precisa ser convertida, o custo não é alto
  • A renderização poderia ser vetorizada em algo como vertex buffers, mas a avaliação é que o método atual já é rápido o suficiente e não precisa voltar ao comportamento de redesenhar tudo, como em UIs immediate mode

Diferenças em relação à Toolbox original do Macintosh

  • O visual começou inspirado no MacOS 8/9, mas com os elementos em escala de cinza removidos; a avaliação foi que o estilo mais flat do System 7 envelheceu melhor, então esse caminho foi escolhido
  • O popup menu é mais próximo do OS8, e a scrollbar se aproxima mais do GS/OS
  • A grande diferença da API é o funcionamento totalmente assíncrono
    • Não dá para desenhar em uma window ou GrafPort com spinloop a qualquer momento como no original
    • Ao mudar o estado da UI, ela se redesenha sozinha quando necessário
  • O processamento de eventos é baseado em callbacks
    • Não há polling para descobrir o que aconteceu na UI
    • Quando um item de menu é clicado ou um atalho de teclado é acionado, o callback de ação é chamado
  • A estrutura conceitual é mais simples que a original
    • Tudo é mui_window ou mui_control
    • windows, menubars e menus são mui_window
    • títulos de menu, itens de menu, todos os elementos dentro da window e linhas separadoras são mui_control

Managers e controles disponíveis

  • Window Manager

    • Suporta criação de janelas e desenho dentro delas
    • Oferece até 15 camadas, clipping, comportamento BringToFront e arraste de janelas
    • O sistema de coordenadas, como no original, fica limitado a dois tipos: screen coordinates e window content coordinates
    • Mantém uma lista de invalid rectangles para evitar redesenhar a janela inteira toda vez
    • zooming e resizing estão em TODO
    • transparent windows não são suportadas de propósito
      • Isso acontece porque as janelas são desenhadas de cima para baixo para otimizar o clipping
      • Para lidar com transparência seria preciso desenhar de baixo para cima, o que forçaria o redesenho de mais conteúdo
      • Ainda assim, é possível aplicar alpha blend da screen inteira da UI no local desejado
  • Menu Manager

    • Suporta menubar, menus, checkmarks e atalhos de teclado
    • Foi feito para parecer com o System 7/8 ou com o GS/OS
    • Há hierarchical menus, mas eles ainda não são idênticos ao original e precisam de melhorias
    • Exibição e rolagem de popups muito grandes estão em TODO
    • O suporte a sticky menus está meio implementado, mas foi desativado porque ainda não está correto
  • Control Manager

    • Suporta buttons, checkboxes, radio buttons, scrollbars verticais e textboxes com quebra de linha
    • O Edit Field ainda está em desenvolvimento, e o Slider está ausente
    • O protótipo do controle de edição de texto funciona bem para entrada de uma linha, mas ainda não se encaixa em caixas de texto com múltiplas linhas
  • List Manager

    • No momento, está quase hardcoded para mostrar nomes de arquivos
    • Lida com arrow keys, page up/down e scroll wheel
    • Como no MacOS original, é possível localizar o item desejado com typeahead
    • O uso de compressão de fonte ou abreviação com ellipsis quando o texto do item é longo demais está em TODO
  • Alerts e Standard File

    • O Alert oferece a caixa de diálogo comum de Cancel + OK
    • Mais tipos de alert estão em TODO
    • O Standard File oferece o clássico diálogo de Open file
      • Esse recurso foi um dos principais objetivos iniciais da biblioteca
      • O diálogo de Save está em TODO
      • Há um popup extra que mostra diretórios usados recentemente
      • Suporta arrow keys, page up/down e busca de arquivos por typeahead
  • Resource Manager

    • Não há Resource Manager
    • A avaliação é que seria necessária uma ferramenta como o ResEdit, então isso ficou fora do escopo atual
    • Existe uma ideia de formato MessagePack para recursos, mas isso foi deixado para depois

Dependências e build

  • A única dependência externa é libpixman
    • libpixman é uma biblioteca para processamento de pixels e fornece recursos de region úteis para clipping
    • Não é tão boa quanto as regions do QuickDraw, mas é considerada suficiente
  • Também há componentes incluídos no código-fonte
    • libcg: um pequeno renderizador antialiasing parecido com o cairo, composto por 2 arquivos
    • stb_truetype.h: usado para carregar fontes TrueType
    • stb_ttc.h: uma extensão de stb_truetype.h que organiza dicionário de fontes/glyphs, hash table, textura de fonte etc.
    • O código de geometria 2D tem mais de 25 anos e também foi incluído em libc3
  • O build usa um Makefile simples, executando make no diretório raiz
  • Para compilar tests, demos e samples, são necessários xcb, xcb-shm, xcb-randr e xkbcommon-x11
  • Se estiver usando o driver binário da Nvidia, para o mui_shell funcionar é preciso adicionar Option "AllowSHMPixmaps" "1" em Device no /etc/X11/xorg.conf

Forma de uso e fluxo de desenvolvimento

  • Como ponto de partida, recomenda-se modificar mui_shell.c e mui_widgets_demo.c
  • ui_mui_shell carrega mui_widgets_demo.so como plugin e o recarrega automaticamente quando detecta mudanças
  • Ao modificar mui_widgets_demo.c, ele é executado novamente após o recarregamento, permitindo criar novos dialogs rapidamente
  • Executar make watch no diretório libmui recompila automaticamente a biblioteca e o mui_shell sempre que houver mudanças
  • Com o auto save do editor, isso permite um fluxo de trabalho de editar, compilar e executar continuamente

O que explicitamente não é oferecido

  • sem dark mode
  • sem suporte a themes
  • sem transparent windows e sem cube effect
  • sticky menus não estão ativados no momento
  • não usa cmake, meson, ninja nem autotools
  • sem bindings para linguagens como Rust, Go e Python
  • não usa frameworks como GTK e QT
  • não usa SDL
  • sem suporte a Wayland

1 comentários

 
GN⁺ 2024-04-02
Comentários do Hacker News
  • A propósito, existe uma fonte TrueType em domínio público que reproduz muito bem a fonte de sistema Chicago original: https://fontlibrary.org/en/font/chicagoflf

    • Pensei em usar Chicago como fonte padrão, mas ela passa uma imagem fixa forte demais
      A Charcoal, usada depois do System 8.x, é bem menos conhecida e, pessoalmente, acho uma melhoria considerável
      Ainda assim, mudar para Chicago na biblioteca é na verdade bem fácil. Além da reprodução mencionada, também existe por aí uma versão TTF “plain” da Chicago original
    • Em relação à observação de que existe uma ótima reprodução da “fonte de sistema Chicago” original, também dá para obter a verdadeira TrueType Chicago desenhada por Bigelow & Holmes baixando o System 7.6.1
      Depois é só converter o TTF para OTF com a ferramenta de linha de comando do FontForge: https://www.macintoshrepository.org/1682-mac-os-7-6-x
      fontforge -script -c 'Open($1); Generate($2);' input_font.ttf output_font.otf
    • Até o macOS moderno inclui uma fonte tailandesa chamada Silom, que usa Chicago nos glifos latinos
  • Muito legal. O Michel fez isso para o emulador Apple II dele, e eu estou usando meio que de brincadeira para substituir o frontend de um emulador Archimedes
    Ainda está no começo, mas se eu consigo entender a API, então com certeza é uma boa API :)

    • Até usar isso num emulador Apple II parece meio uma brincadeira. Na época, os usuários de Apple II queriam que a Apple continuasse com a linha Apple II, e como a empresa focou no Mac e basicamente a abandonou, eles não gostavam muito do Mac
      Mesmo assim, tenho carinho pela interface clássica do Mac
  • Gostei do rasterizador gráfico 2D com abordagem de cabeçalho duplo que este projeto usa: https://github.com/xboot/libcg
    Sempre impressiona ver como dá para criar software poderoso com dependências tão mínimas
    Será que é tão difícil fazer uma biblioteca de UI limpa e poderosa que possa servir como alternativa ao Electron?

    • Não. Mas aí para que serviria toda a memória e desempenho sobrando?
  • Incrível. Em C e sob licença MIT! Se alguém adicionar um shim para a API do AppKit, talvez até possa competir com o GNUstep

    • Ou então é só aplicar um tema do GNUstep. Ele suporta esse tipo de tema
  • Ficou bonito. Queria poder mudar toda a minha interface do macOS para algo assim

    • Se você ativar o modo de alto contraste nas configurações de acessibilidade, fica quase assim
  • Bom projeto. Eu gostava muito da antiga interface clássica do Mac
    Todos os exemplos parecem ótimos, e pelo código de demonstração dos widgets também parece fácil de usar

  • Muito legal. Fico me perguntando quanto trabalho daria ler arquivos de recursos (.rsrc) do resource fork para montar a UI
    Se isso fosse possível, daria para usar o ResEdit :-)