Intuition Windows — Section 3.1 Walkthrough

This article synthesises Section 3.1 ("Windows") of Amiga C for Advanced Programmers by Bleek, Jennrich, Schulz (Abacus / Data Becker, ~1991). Section 3.1 is the longest single section in the chapter (~40 pages, PDF pages 94–132) and covers the Intuition window model: the NewWindow structure, OpenWindow flags, IDCMP event classes, refresh events, gadget attachment, and the standard event loop pattern.

Editorial note: page numbers in this article refer to the PDF page index in the raw OCR source.


Why windows are the most important UI primitive (page 94)

The book opens the section with a strong claim:

"Windows are the most important input/output medium. We wanted to present a detailed description of a complete application you could program in C, then continue to improve upon it throughout this book. We decided on creating a text editor for C programs. Therefore this section supplies you with information about programming fundamental I/O, and selecting what to use from the many options."

The rest of the chapter (and most of Chapter 4) builds the editor example on top of the window primitive. So this section is the most rigorous.


The NewWindow structure (page 95–96)

NewWindow is the declarative descriptor. The book's version (legacy AmigaOS 1.x style):

struct NewWindow {
    SHORT LeftEdge, TopEdge;       /* position */
    SHORT Width, Height;           /* size */
    UBYTE DetailPen, BlockPen;     /* pens */
    ULONG IDCMPFlags;              /* events you want */
    ULONG Flags;                   /* window behaviours */
    struct Gadget *Gadgets;        /* gadget chain */
    struct IntuiText *Title;       /* title text */
    struct Screen *Screen;         /* which screen */
    struct Window *Type;           /* window to clone */
};

The fields map directly to today's OpenWindowTagList() tags. Each field:

Geometry: LeftEdge, TopEdge, Width, Height

  • LeftEdge, TopEdge — top-left corner, in screen pixels. The book notes that LeftEdge = -1 means "centre"; -2 means "snap to default".
  • Width, Height — interior dimensions, excluding the title bar and borders. Standard widths: 320 (LORES), 640 (HIRES).

Pens: DetailPen, BlockPen

Like screens, windows use the pen model. DetailPen is for text; BlockPen is for backgrounds. Pen indices are 0-7.

IDCMPFlags: which events?

IDCMPFlags is a bitmask of event classes. Common flags (book's table on page ~98):

Flag Event
IDCMP_CLOSEWINDOW User clicked the close gadget
IDCMP_REFRESHWINDOW Window contents need redraw
IDCMP_MOUSEBUTTONS Mouse button click/release
IDCMP_MOUSEMOVE Mouse moved over the window
IDCMP_GADGETUP A classic gadget was released
IDCMP_GADGETDOWN A classic gadget was pressed
IDCMP_MENUPICK User selected a menu item
IDCMP_RAWKEY Raw key press/release
IDCMP_VANILLAKEY ASCII-only key (no qualifier info)
IDCMP_ACTIVEWINDOW / IDCMP_INACTIVEWINDOW Window focus change
IDCMP_INTUITICKS Periodic tick (for animation)
IDCMP_IDCMPUPDATE Updates from intuition.library

The book's editor only uses a subset: IDCMP_CLOSEWINDOW | IDCMP_MENUPICK | IDCMP_MOUSEBUTTONS | IDCMP_RAWKEY | IDCMP_REFRESHWINDOW. This is the minimum-viable set.

Modern editors extend with IDCMP_VANILLAKEY for printable keys and IDCMP_NEWSIZE for resize-aware redraw.

Flags: window behaviour

Flags is the most varied field. Book covers extensively (page ~99 onwards). The major flags:

Flag Effect
WFLG_CLOSEGADGET Add a close gadget to title bar
WFLG_SIZEGADGET Add a size gadget (resize)
WFLG_DEPTHGADGET Add a depth gadget
WFLG_DRAGBAR Add a draggable title bar
WFLG_ACTIVATE Bring to front on open
WFLG_GIMMEZEROZERO Reserve inner origin (0,0) instead of (leftedge+border, topedge+titlebar)
WFLG_BORDERLESS No border
WFLG_BACKDROP Make window a backdrop (stays behind other windows)
WFLG_SUPER_BITMAP Allocates a superbitmap refresh region
WFLG_SIMPLE_REFRESH Application is responsible for redraw
WFLG_SMART_REFRESH Intuition queues REFRESH events; redraw once
WFLG_NOCAREREFRESH Don't auto-refresh on size change

Smart vs simple refresh is critical: simple refresh means the application must redraw everything itself; smart refresh lets Intuition queue refreshes and the app redraws once. See intuition/intuition-layer-locking.md for the locking rules.


OpenWindow — the call

struct Window *win = OpenWindow(&nw);
if (!win) {
    /* failure: see IoErr() */
}

The book's editor helper:

if (!(win = (struct Window *)OpenWindow(&nw))) {
    printf("Window can't be opened!\n");
    Close_All();
    exit(FALSE);
}

The book emphasises that OpenWindow() can fail for many reasons (no memory, screen mode not available, screen Lock()ed, etc.) and that the failure path needs to be just as robust as the success path.


The event loop

The book's "hello-world"-equivalent event loop (the pattern is identical for all the example programs):

BOOL done = FALSE;
while (!done) {
    WaitPort(win->UserPort);   /* block until an event arrives */
    while ((msg = GetMsg(win->UserPort))) {
        switch (msg->Class) {
            case IDCMP_CLOSEWINDOW:
                done = TRUE;
                break;
            case IDCMP_REFRESHWINDOW:
                BeginRefresh(win);
                /* ... redraw content ... */
                EndRefresh(win, TRUE);
                break;
            /* ... other events ... */
        }
        ReplyMsg(msg);
    }
}

This is the canonical Intuition event loop. Modern NDK code adds:

  • IExec->Wait() instead of WaitPort() (for exec.library Cleanup)
  • ievent->ie_Class accessor (instead of IntuiMessage.Class)
  • WindowUserData(win) to attach state to the window

But the overall structure is unchanged: wait, get, dispatch, reply.


Refresh events in detail (page ~110)

The book devotes several pages to refresh, because it's the most error-prone part of Intuition programming.

  • IDCMP_REFRESHWINDOW arrives when: window is opened, exposed after being hidden, sized, or moved
  • The application's response is BeginRefresh(win) + draw + EndRefresh(win, complete=TRUE)
  • Within BeginRefresh/EndRefresh, the application can use the window's RastPort for drawing
  • Outside these calls, drawing primitives may not clip correctly

The book gives a worked example for text-refresh (page ~115): the editor redraws the visible text line range in response to a refresh event.


Window ports and message ports

OpenWindow allocates a MsgPort for events; access via win->UserPort. This is your port, not Intuition's — you must ReplyMsg() every message to free the port slot.

The book covers:

  • WaitPort() vs Wait()WaitPort is Intuition's old API; modern code uses IExec->Wait() for multi-source waiting
  • GetMsg() returns one message; loop until NULL
  • ReplyMsg() frees the message structure (which is allocated by intuition.library)

Drag, size, depth, close gadgets

These are system gadgets that Intuition maintains. The book explains:

  • The system gadgets are part of the window's FirstGadget chain
  • They send IDCMP events when activated
  • WFLG_*GADGET flags enable each one
  • Custom system gadgets (e.g. zoom, iconify) came later via WA_Zoom, WA_Iconify tags

The book doesn't cover the modern BOOPSI system gadget replacement (window.class).


Window locking (book's caveats)

The book mentions briefly (page ~120) the gotchas of window locking but doesn't go deep. The serious modern coverage is in intuition/intuition-layer-locking.md, which the book can't anticipate:

  • Always lock the window before drawing outside BeginRefresh/EndRefresh
  • Layer locks must be balanced
  • ObtainGIRPort() is implicit — heavy users may want to avoid it

What's NOT in section 3.1

  • Tag-based window creation (OpenWindowTagList) — comes later. The book predates OS 2.0 tag APIs.
  • BOOPSI window classes (window.class) — modern AmigaOS uses these.
  • Iconify, zoom gadgets — OS 3.x features.
  • Borderless windows with image rendering (WA_Backdrop) is touched briefly; full coverage is in NDK 3.x.
  • Modal windows — the book covers requesters (3.5) instead.
  • Backdrop windows (WFLG_BACKDROP) — covered briefly but not deeply.

Sources

The window model in section 3.1 is essentially identical to the modern AmigaOS intuition.library API; the migration path from NewWindow/OpenWindow to OpenWindowTagList is mechanical, and the event loop pattern carries forward without change.