Intuition Windows, Screens, and the Event Loop

This article deepens the Intuition Library Reference with detailed flag/event reference from Amiga C for Advanced Programmers (Data Becker, 1989). The IDCMP event loop is the heart of every Amiga GUI application.

Window flags (WFLG_*)

Flag Meaning
WFLG_SIZEGADGET Window has a sizing gadget
WFLG_DRAGBAR Window is draggable
WFLG_DEPTHGADGET Window has a depth-arrange gadget
WFLG_CLOSEGADGET Window has a close gadget
WFLG_SIZEBRIGHT Size gadget on right border
WFLG_SIZEBBOTTOM Size gadget on bottom border
WFLG_SMART_REFRESH Intuition auto-refreshes damaged regions
WFLG_SIMPLE_REFRESH Application must handle all refresh
WFLG_SUPER_BITMAP Superbitmap backing store
WFLG_BACKDROP Backdrop window (no title bar, behind others)
WFLG_REPORTMOUSE Report mouse movement events
WFLG_GIMMEZEROZERO GimmeZeroZero coordinate mode (origin at inner window)
WFLG_BORDERLESS No border at all (V36+)
WFLG_ACTIVATE Activate window on open
WFLG_NEWLOOKMENUS Use V39 NewLook menu style

Refresh strategies

  • WFLG_SMART_REFRESH (recommended): Intuition maintains a backing bitmap and auto-repairs damage. Simplest to use.
  • WFLG_SIMPLE_REFRESH: App must handle all repaint via IDCMP_REFRESHWINDOW + BeginRefresh()/EndRefresh(). More complex but less memory.
  • WFLG_SUPER_BITMAP: App maintains a full-size backing bitmap for unlimited scroll/resize. Most flexible but most memory-intensive.

IDCMP event classes

IDCMP Flag Event Message Fields
IDCMP_VANILLAKEY Key press (ASCII) Code = ASCII character
IDCMP_RAWKEY Key press (raw) Code = scancode, Qualifier = modifier state
IDCMP_MOUSEBUTTONS Mouse button Code = SELECTDOWN/UP, MENUDOWN/UP, MIDDLEDOWN/UP
IDCMP_MOUSEMOVE Mouse movement MouseX, MouseY = absolute position
IDCMP_GADGETDOWN Gadget activated IAddress = gadget pointer
IDCMP_GADGETUP Gadget released IAddress = gadget, Code = result code
IDCMP_MENUPICK Menu selected Code = encoded menu path (MENU/ITEM/SUB)
IDCMP_CLOSEWINDOW Close gadget hit (none)
IDCMP_REFRESHWINDOW Needs repaint (none)
IDCMP_INTUITICKS Timer tick (~0.5s) Seconds, Micros = timestamp
IDCMP_NEWSIZE Window resized (none)
IDCMP_NEWPREFS Preferences changed (none)
IDCMP_ACTIVEWINDOW Window activated (none)
IDCMP_INACTIVEWINDOW Window deactivated (none)
IDCMP_DELTAMOVE Relative mouse move MouseX, MouseY = delta

Raw key qualifier bits

Bit Meaning
IEQUALIFIER_LSHIFT Left shift pressed
IEQUALIFIER_RSHIFT Right shift pressed
IEQUALIFIER_CAPSLOCK Caps lock on
IEQUALIFIER_CONTROL Ctrl pressed
IEQUALIFIER_LALT Left Alt pressed
IEQUALIFIER_RALT Right Alt pressed
IEQUALIFIER_LCOMMAND Left Amiga pressed
IEQUALIFIER_RCOMMAND Right Amiga pressed
IEQUALIFIER_NUMERICPAD Key from numeric pad
IEQUALIFIER_REPEAT Key repeat

Mouse button codes

Code Event
SELECTDOWN Left button pressed
SELECTUP Left button released
MIDDLEDOWN Middle button pressed
MIDDLEUP Middle button released
MENUDOWN Right button pressed
MENUUP Right button released

IDCMP_MENUPICK returns an encoded menu path in Code:

MENUNUM    = (Code & MENUMASK)           → which menu (0-9)
ITEMNUM    = ((Code >> ITEMNUMSHFT) & ITEMNUMMASK) → which item
SUBNUM     = ((Code >> SUBNUMSHFT) & SUBNUMMASK)   → which sub-item

Use MENUNUM(code), ITEMNUM(code), SUBNUM(code) macros to extract. NOMENU, NOITEM, NOSUB = -1 (end of chain). Iterate with ItemAddress() to follow the menu pick chain.

The complete event loop

struct IntuiMessage *msg;
ULONG signals;
BOOL running = TRUE;

while (running)
{
    /* Wait for window signal or Ctrl-C */
    signals = Wait(1 << win->UserPort->mp_SigBit | SIGBREAKF_CTRL_C);

    if (signals & SIGBREAKF_CTRL_C)
        break;

    while ((msg = (struct IntuiMessage *)GetMsg(win->UserPort)))
    {
        switch (msg->Class)
        {
            case IDCMP_CLOSEWINDOW:
                running = FALSE;
                break;

            case IDCMP_MOUSEBUTTONS:
                switch (msg->Code)
                {
                    case SELECTDOWN: /* left press at msg->MouseX/Y */ break;
                    case MENUDOWN:   /* right press */ break;
                    case MIDDLEDOWN: /* middle press */ break;
                }
                break;

            case IDCMP_VANILLAKEY:
                if (msg->Code == 27) running = FALSE; /* ESC */
                break;

            case IDCMP_RAWKEY:
                /* msg->Code = raw scancode */
                /* msg->Qualifier = IEQUALIFIER_* bits */
                break;

            case IDCMP_GADGETUP:
                {
                    struct Gadget *gad = (struct Gadget *)msg->IAddress;
                    /* handle gadget interaction */
                }
                break;

            case IDCMP_MENUPICK:
                {
                    UWORD menuNum = MENUNUM(msg->Code);
                    UWORD itemNum = ITEMNUM(msg->Code);
                    /* handle menu selection */
                }
                break;

            case IDCMP_REFRESHWINDOW:
                BeginRefresh(win);
                /* redraw damaged areas */
                EndRefresh(win, TRUE);
                break;

            case IDCMP_INTUITICKS:
                /* periodic update (~0.5s) */
                break;

            case IDCMP_NEWSIZE:
                /* window resized — re-layout */
                break;
        }
        ReplyMsg((struct Message *)msg);  /* ALWAYS reply */
    }
}

Rules: Always ReplyMsg() every message. Use GT_GetIMsg()/GT_ReplyIMsg() if using GadTools. Don't call Intuition functions inside BeginRefresh()/EndRefresh() (layer lock held).

See Also


Sources: Bleek, Jennrich, Schulz, "Amiga C for Advanced Programmers" (Data Becker/Abacus, 1989), Chapter 3. Raw: raw/amiga-c-advanced/advanced-c-extract.md; raw/tutorials/amiga-c-advanced-full.md Updated: 2026-08-09 Updated: 2026-08-04