amiga-bootcamp/09_intuition/intuition_base.md
Ilia Sharin 4d136b0672 doc: Intuition bootcamp — comprehensive enrichment of all subsystem articles
Transformed 8 stub articles (720 lines total) into full bootcamp-grade
references (5,100+ lines) with architecture diagrams, complete code
examples, struct field references, pitfalls, and best practices.

IDCMP (idcmp.md — 1,060 lines):
- IntuiMessage field reference with types, sizes, value ranges
- Use-case cookbook: double-click, rubber-band, multi-signal, BOOPSI
- When to use IDCMP vs alternatives (decision flowchart)
- 5 named antipatterns with WRONG/RIGHT code
- Memory safety checklist and defensive event loop template
- Cross-platform comparison table (Win32, X11, Cocoa, Qt)

Input Events (input_events.md — 850 lines):
- Event class routing and QoS analysis (priority-as-QoS hierarchy)
- Intuition consumption table (what survives the handler chain)
- lowlevel.library bypass for CD32/game input
- Latency analysis with pipeline timing budget (68000 vs 68040)
- Input strategy comparison (IDCMP vs handler vs direct hardware)
- Game input patterns: direct HW polling, CIA keyboard, hybrid handler
- Signal pattern for proper handler→application communication

Windows (windows.md — 370 lines):
- Window anatomy diagram, WA_ tag reference tables
- Refresh modes comparison (Simple/Smart/SuperBitMap)
- Window types: standard, backdrop, borderless, GimmeZeroZero
- Coordinate system, border offsets, struct Window fields
- Modification API (move, resize, title, busy pointer)

Gadgets (gadgets.md — 403 lines):
- Three-generation evolution (raw/GadTools/BOOPSI)
- Complete GadTools lifecycle with setup, creation, events, cleanup
- Runtime state updates (GadTools vs raw Intuition)
- Raw struct Gadget: GFLG_*, GACT_*, GTYP_* flag tables
- Proportional and string gadget internals

BOOPSI (boopsi.md — 505 lines):
- Class hierarchy Mermaid diagram
- Method dispatch sequence diagram
- ICA interconnection architecture (icclass, modelclass, ICTARGET_IDCMP)
- Full custom gadget class tutorial (4 steps with complete code)
- Built-in class reference table
- C++/Qt analog comparison table

Menus (menus.md — 378 lines):
- Menu hierarchy diagram (Menu → Item → Sub-Item)
- GadTools NewMenu workflow with field reference
- Event handling with multi-select chain walking
- Checkmark/mutual exclusion, sub-menus, dynamic modification
- Keyboard shortcut system (single-char and NM_COMMANDSTRING)

Requesters (requesters.md — 370 lines):
- EasyRequest return value logic table
- ASL file requester with multi-select and full tag reference
- ASL font and screenmode requesters
- Non-blocking BuildEasyRequest/SysReqHandler pattern
- Requester state persistence

IntuitionBase (intuition_base.md — 267 lines):
- Library version table (OS 1.2 through 3.2.x)
- Struct field reference with safety annotations
- ViewLord architecture diagram
- LockIBase vs Forbid/Permit guidance
- Complete library function overview (5 categories)

README index updated with enriched article descriptions.
2026-04-23 17:29:18 -04:00

9.5 KiB

← Home · Intuition

IntuitionBase — Global GUI State

What Is IntuitionBase?

IntuitionBase is the library base structure for intuition.library — the heart of the Amiga's graphical user interface. Unlike modern systems where the window manager is a separate process, Intuition is a shared library loaded into the system's address space. IntuitionBase contains the global state for all screens, windows, and input routing.

Every Amiga GUI program begins by opening this library:

struct IntuitionBase *IntuitionBase;
IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 39);
if (!IntuitionBase)
{
    /* Running on a system older than OS 3.0 — exit gracefully */
    return RETURN_FAIL;
}

Version Requirements

Version OS Release Key Features Added
33 1.2 Original Intuition
36 2.0 TagList APIs, public screens, BOOPSI, GadTools
37 2.04 Improved memory handling
39 3.0 New-look menus, enhanced DrawInfo, ChangeWindowBox()
40 3.1 AppWindow/AppIcon improvements
47 3.2 OS 3.2 additions (enhanced backfill, new screen tags)
50+ 3.2.x Continued 3.2 line improvements

struct IntuitionBase

/* intuition/intuitionbase.h — NDK 3.9 */
struct IntuitionBase {
    struct Library  LibNode;          /* Standard library node */
    struct View     ViewLord;         /* Master graphics View */
    struct Window  *ActiveWindow;     /* Currently active window */
    struct Screen  *ActiveScreen;     /* Currently active screen */
    struct Screen  *FirstScreen;      /* Head of screen linked list */
    ULONG           Flags;            /* Internal state flags */
    WORD            MouseY, MouseX;   /* Current mouse position */
    ULONG           Seconds, Micros;  /* Current timestamp */
    /* ... many private/internal fields follow ... */
};

Field Reference

Field Type Description Safe to Read?
LibNode struct Library Standard Exec library header — version, open count, etc. Yes
ViewLord struct View Master View structure — controls the entire display through the Copper No — use graphics.library functions
ActiveWindow struct Window * Pointer to the currently active window Yes (with Forbid()/Permit())
ActiveScreen struct Screen * Pointer to the currently active screen Yes (with Forbid()/Permit())
FirstScreen struct Screen * Head of the screen list (front-to-back order) Yes (with Forbid()/Permit())
Flags ULONG Internal state flags No — private
MouseY, MouseX WORD Absolute mouse position on active screen Yes
Seconds, Micros ULONG System timestamp of last input event Yes

Warning

: Fields beyond those listed above are private and change between OS versions. Accessing undocumented fields will break your program on different OS releases.


Using IntuitionBase

Reading the Active Window

/* Must protect with Forbid/Permit — ActiveWindow can change asynchronously */
Forbid();
struct Window *active = IntuitionBase->ActiveWindow;
if (active)
{
    /* Read what you need while protected */
    STRPTR title = active->Title;
    /* ... */
}
Permit();

Walking the Screen List

Forbid();
struct Screen *scr = IntuitionBase->FirstScreen;
while (scr)
{
    Printf("Screen: %s (%ldx%ld)\n",
        scr->Title ? scr->Title : "(no title)",
        scr->Width, scr->Height);
    scr = scr->NextScreen;
}
Permit();

Reading Mouse Position

/* Global mouse position (relative to active screen) */
WORD mx = IntuitionBase->MouseX;
WORD my = IntuitionBase->MouseY;

/* For window-relative position, use Window->MouseX/MouseY instead */

The ViewLord

IntuitionBase->ViewLord is the master struct View — the top-level graphics structure that controls the entire display. Intuition builds a Copper list from this View to render all screens.

graph TB
    VL["ViewLord<br/>(struct View)"] --> VP1["ViewPort 1<br/>Workbench Screen"]
    VL --> VP2["ViewPort 2<br/>Custom Screen"]
    VL --> VP3["ViewPort 3<br/>Game Screen"]
    VP1 --> BM1["BitMap 1"]
    VP2 --> BM2["BitMap 2"]
    VP3 --> BM3["BitMap 3"]

    style VL fill:#e8f4fd,stroke:#2196f3,color:#333

You should never modify the ViewLord directly. Use MakeScreen(), RethinkDisplay(), or RemakeDisplay():

/* After changing a screen's ViewPort (e.g., palette): */
MakeScreen(scr);        /* Rebuild this screen's Copper list */
RethinkDisplay();       /* Rebuild the entire display from ViewLord */

/* Or the combined version: */
RemakeDisplay();        /* MakeScreen + RethinkDisplay for all screens */

Library Functions Overview

Screen Management

Function Description
OpenScreenTagList() Open a new screen with tag-based configuration
CloseScreen() Close a screen (all windows must be closed first)
LockPubScreen() Lock a public screen by name (prevents closing)
UnlockPubScreen() Release a public screen lock
PubScreenStatus() Set public screen state (available / private)
GetScreenDrawInfo() Get pen and font information for a screen
FreeScreenDrawInfo() Release DrawInfo
ScreenToFront() / ScreenToBack() Change screen depth order
MoveScreen() Move screen vertically

Window Management

Function Description
OpenWindowTagList() Open a new window with tag-based configuration
CloseWindow() Close a window
ActivateWindow() Make a window active
WindowToFront() / WindowToBack() Change window depth
MoveWindow() / SizeWindow() Adjust window position/size
ChangeWindowBox() Set absolute position and size
SetWindowTitles() Change window and screen titles
SetWindowPointer() Set custom or busy pointer

Gadget Management

Function Description
AddGadget() / RemoveGadget() Add/remove gadgets from windows
RefreshGList() Redraw gadget(s)
SetGadgetAttrs() Set BOOPSI gadget attributes
ModifyIDCMP() Change IDCMP flags dynamically

Menu Management

Function Description
SetMenuStrip() Attach menu strip to window
ClearMenuStrip() Remove menu strip from window
OnMenu() / OffMenu() Enable/disable menu items
ItemAddress() Get MenuItem pointer from packed menu number

Requesters and Dialogs

Function Description
EasyRequest() Show a simple message dialog
BuildEasyRequest() Create a non-blocking requester
SysReqHandler() Poll a non-blocking requester
FreeSysRequest() Free a non-blocking requester
AutoRequest() Legacy two-button dialog (OS 1.x)

Rendering Support

Function Description
DrawBorder() Draw a struct Border
PrintIText() Draw struct IntuiText
BeginRefresh() / EndRefresh() Simple-refresh window support
LockIBase() / UnlockIBase() Lock IntuitionBase for multi-field reads

LockIBase — Safe Multi-Field Access

When reading multiple IntuitionBase fields that must be consistent, use LockIBase():

ULONG lock = LockIBase(0);

struct Window *active = IntuitionBase->ActiveWindow;
struct Screen *screen = IntuitionBase->ActiveScreen;
/* Both refer to the same moment in time */

UnlockIBase(lock);

Without the lock, ActiveWindow could change between reading it and reading ActiveScreen — giving you a window on a different screen than expected.

LockIBase() is heavier than Forbid()/Permit() — use it only when you need atomic multi-field reads. For single field access, Forbid()/Permit() is sufficient.


Pitfalls

1. Not Checking Library Version

Opening intuition.library version 0 succeeds on any system, but tag-based functions (OpenWindowTags, OpenScreenTags) require version 36+. Always specify the minimum version you need.

2. Reading Private Fields

Many tools and examples from the late '80s directly access internal IntuitionBase fields (like internal semaphores or the gadget environment). These fields moved between OS versions — code that worked on 1.3 crashed on 2.0, and code that worked on 3.1 crashes on 3.2.

3. Writing to IntuitionBase

Never write to IntuitionBase fields directly. Use the provided API functions. Direct writes bypass Intuition's internal state management and cause corruption.

4. Forgetting Forbid/Permit

ActiveWindow, ActiveScreen, and FirstScreen can change at any time (multitasking). Reading without Forbid()/Permit() or LockIBase() creates a race condition.


Best Practices

  1. Open with the minimum version you need — e.g., OpenLibrary("intuition.library", 39) for OS 3.0 features
  2. Use LockIBase() for atomic multi-field reads from IntuitionBase
  3. Use Forbid()/Permit() for quick single-field reads
  4. Never access undocumented fields — they change between OS versions
  5. Never modify IntuitionBase — use API functions
  6. Close the library when done — CloseLibrary((struct Library *)IntuitionBase)
  7. Check the library pointer before using any functions — it may be NULL on pre-2.0 systems

References

  • NDK 3.9: intuition/intuitionbase.h, intuition/intuition.h
  • ADCD 2.1: OpenLibrary(), LockIBase(), UnlockIBase()
  • AmigaOS Reference Manual (RKRM): Libraries, Chapter 2 — Intuition Overview
  • See also: Screens, Windows, IDCMP