- Libmui는 Macintosh Classic “Toolbox” API의 상당 부분을 복제한 UI 라이브러리로, 완전 구현은 아니지만 MII Apple //e emulator와 간단한 애플리케이션에 필요한 기능을 제공함
- MII용 UI 라이브러리로 시작했으며, 의존성이 많거나 “Arrow Keys + Return + Escape”식 게임형 메뉴가 아닌 수작업으로 배치한 UI를 목표로 함
- 렌더링은 ARGB 버퍼에 그린 뒤 OpenGL 텍스처나 X11/XCB shared pixmap으로 복사하는 방식이며, invalid region을 추적해 필요한 영역만 다시 그림
- API는 원래 Macintosh Toolbox와 달리 비동기·콜백 기반으로 동작하며, 상태를 바꾸면 UI가 필요할 때 다시 그리고 이벤트는 폴링 대신 콜백으로 전달됨
- Window, Menu, Control, List, Alert, Standard File 기능을 갖췄지만 zooming, resizing, Save dialog, dark mode, theme, Wayland, GTK/QT/SDL, Rust/Go/Python 바인딩은 제공하지 않음
Libmui가 만드는 것
- Libmui는 Macintosh Classic “Toolbox” API를 많이 복제한 라이브러리임
- 완전한 구현은 아니지만 몇 가지 간단한 애플리케이션과 MII Apple //e emulator에 필요한 부분을 포함함
- MII용 UI 라이브러리가 필요했고, 의존성이 많지 않으면서 게임식 메뉴 조작에 치우치지 않은 UI를 원한 것이 출발점임
- Nuklear immediate mode UI를 먼저 써봤지만, 외형이 마음에 들지 않고 커스텀 작업에 제한이 크며 레이아웃 엔진이 원하는 위치와 다르게 배치한다고 판단함
- immediate mode UI가 내부적으로 해시 기반 상태를 유지하며, 해시 충돌이 실제 디버깅 문제를 만들 수 있다는 경험도 배경이 됨
- 목표는 레이아웃 엔진이 알아서 정하는 UI보다 직접 다듬은 UI에 가까움
렌더링과 동작 모델
- Libmui는 ARGB 버퍼로 된 “screen”에 UI를 그림
- MII에서는 이 버퍼를 OpenGL 텍스처로 오버레이함
- example 폴더의 playground 데모는 X11 창에 XCB shared pixmap으로 복사하며, remote X11에서도 동작함
- 오래된 OS처럼 invalid region을 추적해 필요한 부분만 다시 그림
- 전체를 매번 다시 그리지 않아 overdraw가 매우 적음
- 16비트 framebuffer 등에 그리려면 ARGB 출력에서 직접 변환해야 함
- dirty region만 변환하면 되므로 부담이 크지 않음
- 렌더링을 vertex buffer 등으로 벡터화할 수도 있지만, 현재 방식이 충분히 빠르고 immediate mode UI처럼 전체를 다시 그리는 동작으로 돌아갈 필요가 없다고 봄
원래 Macintosh Toolbox와 다른 점
- 외형은 MacOS 8/9에서 시작했지만 grayscale 요소를 제거한 느낌이며, System 7의 flat한 모습이 더 잘 늙었다고 판단해 그쪽을 선택함
- popup menu는 OS8에 더 가깝고, scrollbar는 GS/OS 쪽에 더 가까움
- API의 큰 차이는 완전 비동기 동작임
- 원래처럼 아무 때나 window나 GrafPort에 spinloop로 그릴 수 없음
- UI 상태를 바꾸면 필요할 때 UI가 스스로 다시 그림
- 이벤트 처리는 콜백 기반임
- UI에 무슨 일이 있었는지 폴링하지 않음
- 메뉴 아이템 클릭이나 키보드 단축키 입력이 발생하면 action 콜백이 호출됨
- 개념 구조는 원본보다 단순함
- 모든 것은
mui_window또는mui_control임 - windows, menubars, menus는
mui_window - menu titles, menu items, window 안의 모든 요소, separator lines는
mui_control
- 모든 것은
제공하는 매니저와 컨트롤
-
Window Manager
- 창 생성과 창 안 그리기를 지원함
- 최대 15개 layer, clipping, BringToFront 동작, 창 드래그를 지원함
- 좌표계는 원래와 비슷하게 screen coordinates와 window content coordinates 2개로 제한함
- invalid rectangle 목록을 관리해 전체 창을 매번 다시 그리지 않음
- zooming과 resizing은 TODO임
- transparent windows는 의도적으로 지원하지 않음
- top-down 방식으로 창을 그려 clipping을 최적화하기 때문임
- 투명도를 처리하려면 bottom-up으로 그려야 하고, 더 많은 내용을 다시 그리게 됨
- 전체 UI screen을 원하는 곳에 alpha blend하는 것은 가능함
-
Menu Manager
- menubar, menus, checkmarks, keyboard shortcuts를 지원함
- System 7/8 또는 GS/OS처럼 보이도록 만들어짐
- hierarchical menus가 있지만 원본과 완전히 같지는 않으며 개선이 필요함
- 아주 큰 popup의 표시와 스크롤은 TODO임
- sticky menus 지원은 반쯤 구현됐지만 아직 맞지 않아 비활성화됨
-
Control Manager
- buttons, checkboxes, radio buttons, vertical scrollbars, wrapping textboxes 등을 지원함
- Edit Field는 작업 중이며 Slider는 빠져 있음
- text edit control 프로토타입은 한 줄 입력에는 괜찮지만 여러 줄 텍스트 박스에는 아직 맞지 않음
-
List Manager
- 현재는 파일명을 표시하는 용도에 가깝게 하드코딩돼 있음
- arrow keys, page up/down, scroll wheel을 처리함
- 원래 MacOS처럼 typeahead로 원하는 항목을 찾을 수 있음
- 항목 텍스트가 너무 길 때 font compression이나 ellipsis abbreviation을 쓰는 기능은 TODO임
-
Alerts와 Standard File
- Alert는 일반적인 Cancel + OK 대화상자를 제공함
- 더 많은 alert 종류는 TODO임
- Standard File은 클래식한 Open file dialog를 제공함
- 이 기능은 라이브러리의 초기 주요 목표 중 하나였음
- Save dialog는 TODO임
- 최근 사용한 디렉터리를 보여주는 추가 popup이 있음
- arrow keys, page up/down, typeahead 파일 검색을 지원함
-
Resource Manager
- Resource Manager는 없음
- ResEdit 같은 도구가 필요하다고 보고, 현재 범위에서는 제외함
- 리소스용 MessagePack 형식 아이디어는 있지만 이후 작업으로 남아 있음
의존성과 빌드
- 외부 의존성은 libpixman뿐임
- libpixman은 픽셀 처리용 라이브러리이며 clipping에 유용한 region 기능을 제공함
- QuickDraw의 region만큼 좋지는 않지만 충분하다고 봄
- 소스에 포함된 구성 요소도 있음
- libcg: cairo와 비슷한 작은 antialiased renderer이며 2개 파일로 구성됨
- stb_truetype.h: TrueType font 로딩에 사용됨
stb_ttc.h:stb_truetype.h확장으로 font/glyph dictionary, hash table, font texture 등을 구성함- 2D geometry 코드는 25년 넘게 된 코드이며 libc3에도 포함됐음
- 빌드는 루트 디렉터리에서
make를 실행하는 단순한 Makefile 방식임 - tests, demos, samples 빌드에는
xcb,xcb-shm,xcb-randr,xkbcommon-x11이 필요함 - Nvidia binary driver를 쓰는 경우
mui_shell이 동작하려면/etc/X11/xorg.conf의Device에Option "AllowSHMPixmaps" "1"을 추가해야 함
사용 방식과 개발 워크플로
- 시작점으로는
mui_shell.c와mui_widgets_demo.c를 수정해보는 방식이 권장됨 ui_mui_shell은mui_widgets_demo.so를 plugin으로 로드하고, 변경을 감지하면 자동으로 다시 로드함mui_widgets_demo.c를 수정하면 재로드 후 다시 실행되므로 새 dialog를 빠르게 만들 수 있음make watch를libmui디렉터리에서 실행하면 변경 시 라이브러리와mui_shell을 자동으로 다시 빌드함- 에디터의 auto save와 함께 쓰면 수정하면서 계속 빌드·실행되는 워크플로를 만들 수 있음
명시적으로 제공하지 않는 것
- dark mode 없음
- theme 지원 없음
- transparent windows와 cube effect 없음
- sticky menus는 현재 활성화되지 않음
cmake,meson,ninja, autotools를 쓰지 않음- Rust, Go, Python 같은 언어 바인딩 없음
- GTK, QT 같은 프레임워크를 쓰지 않음
- SDL을 쓰지 않음
- Wayland 지원 없음