MUI — Magic User Interface

MUI (Magic User Interface) is a BOOPSI-based, object-oriented GUI system for Amiga, written by Stefan Stuntz (copyright 1992-97). The 3.8 developer archive is the third major GUI toolkit now documented in this wiki, alongside classic GadTools and OS 3.2's ReAction. Where GadTools wraps classic Intuition gadgets and ReAction ships official OS 3.2 classes, MUI was the dominant third-party GUI toolkit — the look of most commercial and shareware Amiga software of the late 1990s.

MUI's defining ideas are an automatic layout engine (the programmer never sizes or positions anything) and a declarative notification mechanism (objects are wired together by attribute change, so the main loop is just a Wait()). It predates ReAction by years and is unrelated to it; both are BOOPSI class systems but with incompatible APIs and philosophies.

The class tree

MUI classes are all subclasses of BOOPSI's rootclass. Notify is the superclass of everything else — it implements the notification mechanism. Below it:

rootclass  (BOOPSI base)
└── Notify
    ├── Application   (one per program; owns windows, ARexx, commodities)
    ├── Window        (wraps an Intuition window; has one root object)
    └── Area          (base class for all visible GUI elements)
        ├── Rectangle, Image, Text, String, Prop, Gauge, Scale, Boopsi,
        │   Colorfield
        ├── List  → Floattext, Volumelist, Scrmodelist, Dirlist
        └── Group (handles layout)
            ├── Virtgroup, Scrollgroup, Scrollbar, Listview, Radio,
            │   Cycle, Slider, Coloradjust, Palette

Each class ships as a separate shared library; the developer archive includes 66 autodoc files (per-class MUI_*.doc plus MUImaster.doc). muimaster.library provides the creation/disposal/class-management functions and embeds several of the standard classes.

The application object tree

A MUI program is one big object tree (distinct from the class tree above):

  • Application — exactly one. Handles user input, ARexx, commodities. Owns zero or more windows.
  • Window — owns exactly one root object (an Area subclass, almost always a Group).
  • Group — owns one or more children, each an Area subclass. Children can themselves be groups, nesting arbitrarily.

Only these three types may have children.

The layout engine

This is MUI's headline feature. The programmer never sets sizes or positions. Instead:

  1. Every object advertises its minimum and maximum dimensions.
  2. Before opening a window, MUI queries all objects and computes the window's extreme sizes.
  3. On open (and on every resize), MUI runs a layout pass from the root down, distributing space by group orientation (horizontal/vertical) and each child's weight.
  4. Objects never shrink below their minimum or grow beyond their maximum.

Result: every MUI program is fully screen-, window-size- and font-sensitive for free. Resizing the window just triggers another layout pass.

Building the UI with macros

The object tree is built in one nested macro call. XxxObject opens a bracket, End closes it. Complete-object macros exist too (SimpleButton("Cancel")). A file-requester window:

VGroup,
    Child, HGroup,
        Child, FileListview(),
        Child, DeviceListview(),
        End,
    Child, PathGadget(),
    Child, FileGadget(),
    Child, HGroup,
        Child, OkayButton(),
        Child, CancelButton(),
        End,
    End;

VGroup/HGroup create vertical/horizontal groups. If you need many objects of one type (e.g. 200 buttons), convert the macro to a function to save memory.

The notification mechanism

Notification is the central control flow of a MUI app. Most objects have attributes describing their state; notification fires a method on a destination object whenever a source attribute hits a trigger value.

DoMethod(obj, MUIM_Notify, TrigAttr, TrigVal, DestObj, FollowParams, /* method... */);

The FollowParams count is how many parameters follow it — set it correctly, because MUI must save them. Special trigger values:

  • MUIV_EveryTime — fire on every change of the attribute.
  • MUIV_TriggerValue — in the fired method, substitute the attribute's current value.

Wire a scrollbar to a list (a full listview, no loop code):

DoMethod(sbar, MUIM_Notify, MUIA_Prop_First, MUIV_EveryTime,
         list, 3, MUIM_Set, MUIA_List_TopPixel, MUIV_TriggerValue);

Open a window from a button:

DoMethod(button, MUIM_Notify, MUIA_Pressed, FALSE,
         window, 3, MUIM_Set, MUIA_Window_Open, TRUE);

Attributes change either from SetAttrs() or from user input (e.g. dragging a prop gadget continuously updates MUIA_Prop_First). Watch for endless loops when binding two objects bidirectionally.

The event loop

Once the tree and notifications are set up, the main loop is just a Wait(). From the canonical MUI-Demo.c:

ULONG signal;
BOOL running = TRUE;

while (running)
{
    switch (DoMethod(app, MUIM_Application_Input, &signal))
    {
        case MUIV_Application_ReturnID_Quit:
            running = FALSE;
            break;
        /* ...handle other return IDs... */
    }
    if (running && signal) Wait(signal);
}

MUIM_Application_Input processes pending input and returns a return ID that you previously requested via a MUIM_Application_ReturnID notification; MUIV_Application_ReturnID_Quit ends the loop. signal receives the signal mask to wait on. (MUIM_Application_NewInput is the newer variant.) The demo's own commentary: "The main loop of this demo program simply consists of a Wait(). Once set up, MUI handles all user actions concerning the GUI automatically."

Compare this to ReAction's RA_HandleInput() loop returning WMHI_* codes — structurally similar, but MUI's notification-first model means most apps need almost no loop logic at all.

The Application class

Key attributes (from MUI_Application.doc): MUIA_Application_Title, _Version, _Copyright, _Author, _Description, _Base (the prefs filename), _Window (add a window), _Menustrip, _UseCommodities, _UseRexx, _RexxHook, _Iconified, _SingleTask, _DropObject.

Key methods: MUIM_Application_Input/NewInput (event dispatch), _ReturnID (request a return ID on attribute change), _AddInputHandler/_RemInputHandler (async handlers), _PushMethod (deferred invocation), _Load/_Save (prefs), _ShowHelp, _OpenConfigWindow, _AboutMUI.

muimaster.library API

MUI_NewObjectA / MUI_DisposeObject (create/destroy), MUI_MakeObjectA (build standard objects), MUI_Redraw, MUI_RequestA (modal requester), MUI_ObtainPen / MUI_ReleasePen (DrawInfo pens), MUI_GetClass / MUI_FreeClass (class pointers), MUI_CreateCustomClass / MUI_DeleteCustomClass (custom classes), MUI_RequestIDCMP / MUI_RejectIDCMP (filter raw IDCMP), MUI_AllocAslRequest / MUI_AslRequest / MUI_FreeAslRequest (file requesters).

Custom classes

Since MUI 2.0 you can write private classes just like the builtins. "Beneath the BOOPSI gadget interface, private classes are the only way to have custom gadgets in a MUI window. Drawing into windows directly from the applications task is illegal and will surely lead into lots of problems!"

A custom class implements the BOOPSI lifecycle methods — OM_NEW/OM_DISPOSE, MUIM_Setup/MUIM_Cleanup, MUIM_AskMinMax, MUIM_Show/MUIM_Hide, MUIM_Draw, MUIM_HandleInput, OM_SET/OM_GET — and is distributed as an external class library (MCC/MCP). The ExtClasses/MCC_Tron example in the archive demonstrates a complete one. Custom classes are how the MUI ecosystem extended far beyond the 30-odd builtin classes.

Licensing

MUI's license split it from free-as-in-free toolkits:

  • Freely distributable software (PD, freeware, shareware) may use MUI for free. You may not redistribute MUI's libraries/classes/prefs with your app — users fetch MUI themselves.
  • Commercial software pays a licence, roughly US$50 to US$500 depending on scale (rule of thumb: 5× the retail price). The licence covers current and future MUI versions for current and future versions of your product, and permits redistributing the master library, classes and a non-nag preferences program.

This licensing model is why MUI became the de-facto shareware standard but was less ubiquitous in low-margin commercial titles — and why the open-source Zune reimplementation later appeared for AROS.

Developer archive contents

  • Autodocs/ — 66 per-class autodocs
  • Docs/MUIdev.guide — the programmer manual (AmigaGuide, from texinfo)
  • Docs/Policies — the licensing policy
  • C/Include/, C/DLib/ (DICE C), C/Manx/ (Aztec C) — language interfaces
  • C/Examples/ — ~20 documented demos (MUI-Demo.c, DragnDrop.c, InputHandler.c, Layout.c, Menus.c, Class1/2/3.c, AppWindow.c, Pages.c, Popup.c, EnvBrowser.c, psi.c)
  • FD/ — function descriptors
  • ExtClasses/MCC_Tron/ — example external custom class

MUI vs ReAction vs GadTools

GadTools ReAction MUI
Era V36 (KS 2.0) V47 (OS 3.2, 2021) 1992-97 (third-party)
Base Classic Intuition gadgets BOOPSI classes BOOPSI classes
Layout Manual (or none) Manual via macros Fully automatic
Event model IDCMP messages RA_HandleInput()WMHI_* MUIM_Application_Input + notification
Distribution ROM/lib OS 3.2 class libs Shared libs + custom classes (MCC/MCP)
Custom gadgets No (use raw BOOPSI) Subclass classes Custom classes (MCC/MCP)
Adoption ROM software OS 3.2 apps Dominant third-party/shareware GUI

See Also


Sources: Stefan Stuntz, MUI 3.8 Developer Archive (ReadMe, MUIdev.guide, Policies, MUImaster.doc, MUI_Notify.doc, MUI_Application.doc, MUI-Demo.c), 1992-1997. Raw: raw/gui/mui-3.8-developer-kit.md Updated: 2026-08-04