[← Home](../README.md) # Intuition — GUI Subsystem Overview Intuition is the AmigaOS windowing system and user interface manager. It sits between applications and the low-level graphics/input hardware, providing screens, windows, gadgets, menus, and an event-driven message passing system. Unlike modern desktop GUIs, Intuition operates with **zero memory protection** and **cooperative multitasking** — every application directly shares hardware resources. ## Section Index | File | Description | |---|---| | [intuition_base.md](intuition_base.md) | IntuitionBase — library versioning, global state fields, ViewLord, LockIBase, function overview | | [screens.md](screens.md) | Screens — Copper mechanics, display modes (OCS/ECS/AGA/RTG), dragging, resolution tables, screen type decision guide, 5 antipatterns, screen flipping/borderless/PAL-NTSC cookbooks, modern analogies, 7 FAQ | | [windows.md](windows.md) | Windows — WA_ tags, refresh modes, window types, coordinate system, lifecycle, 5 antipatterns, decision guide, 3 cookbooks, modern analogies, 7 FAQ | | [gadgets.md](gadgets.md) | Gadgets — GadTools creation, raw struct Gadget, prop/string gadgets, runtime updates, 5 antipatterns, GadTools→BOOPSI migration guide, form cookbook, historical timeline, 6 FAQ | | [menus.md](menus.md) | Menus — GadTools NewMenu, event handling, multi-select, checkmarks, keyboard shortcuts, render chain diagram, 5 antipatterns, lifecycle cookbook, 6 FAQ | | [requesters.md](requesters.md) | Requesters — EasyRequest, ASL file/font/screenmode dialogs, non-blocking pattern | | [idcmp.md](idcmp.md) | IDCMP — event architecture, class reference, shared ports, antipatterns, use-case cookbook | | [boopsi.md](boopsi.md) | BOOPSI — OOP dispatcher model, ICA interconnection, custom class tutorial, class hierarchy | | [input_events.md](input_events.md) | Input Events — handler chain, QoS/priority, Commodities, latency analysis, game input | | [commodities.md](commodities.md) | Commodities Exchange — background input filtering, hotkeys, CxObjects, Exchange control | | **[frameworks/](frameworks/)** | **GUI Frameworks: MUI, ReAction, BGUI** | --- ## System Architecture — Where Intuition Fits ```mermaid graph TB subgraph "User Applications" APP1["Application 1"] APP2["Application 2"] WB["Workbench"] end subgraph "GUI Layer" INT["intuition.library
Screens, Windows, IDCMP"] GT["gadtools.library
Standard Gadgets"] ASL["asl.library
File/Font Requesters"] BOOPSI["BOOPSI Framework
OOP Gadgets"] end subgraph "Graphics Layer" GFX["graphics.library
RastPort, BitMap, Draw"] LAY["layers.library
Clipping, Damage Repair"] COP["Copper
Display List DMA"] BLT["Blitter
Area Fill, Scroll"] end subgraph "Input Layer" INP["input.device
Raw Input Stream"] KBD["keyboard.device"] GP["gameport.device
Mouse / Joystick"] CON["console.device
Text I/O"] end subgraph "Hardware" CUSTOM["Custom Chips
Denise/Lisa · Paula"] CIA_["CIA-A / CIA-B
Keyboard, Timers"] end APP1 & APP2 & WB --> INT INT --> GT & ASL & BOOPSI INT --> GFX GFX --> LAY GFX --> COP & BLT INT --> INP INP --> KBD & GP INP --> CON KBD --> CIA_ GP & COP & BLT --> CUSTOM ``` --- ## Data Flow — From Keypress to Application ```mermaid sequenceDiagram participant HW as CIA-A / Keyboard participant KBD as keyboard.device participant INP as input.device participant INT as Intuition participant WIN as Active Window participant APP as Application HW->>KBD: IRQ (key scancode) KBD->>INP: InputEvent (IECLASS_RAWKEY) INP->>INT: Input handler chain Note over INT: Intuition checks:
Menu shortcut?
System key?
Gadget activation? INT->>WIN: Route to active window WIN->>APP: IDCMP IntuiMessage
(via MsgPort) APP->>APP: ReplyMsg() when done ``` --- ## Screen / Window / Gadget Hierarchy ```mermaid graph TB subgraph "Display Hardware" VP["ViewPort
(Copper-driven display)"] end subgraph "Screen Layer" SCR["Screen
sc_ViewPort, sc_RastPort
sc_BitMap, sc_Flags"] end subgraph "Window Layer" W1["Window A
IDCMP flags, RastPort"] W2["Window B
IDCMP flags, RastPort"] end subgraph "Gadget Layer" G1["System Gadgets
Close, Depth, Size, Drag"] G2["GadTools Gadgets
Button, Slider, ListView"] G3["BOOPSI Objects
Custom gadgets via OOP"] end subgraph "Menu Layer" M1["MenuStrip
Menu → MenuItem → SubItem"] end VP --> SCR SCR --> W1 & W2 W1 --> G1 & G2 & G3 W1 --> M1 W2 --> G1 ``` ### Ownership Rules | Object | Owned By | Lifetime | |---|---|---| | **Screen** | Creator task (or Workbench) | Until `CloseScreen()` — all windows must close first | | **Window** | Creator task | Until `CloseWindow()` — must drain IDCMP port first | | **Gadget** | Window | Attached via `AddGList()`, removed before window close | | **Menu** | Window | Attached via `SetMenuStrip()`, cleared via `ClearMenuStrip()` | | **RastPort** | Window/Screen | Borrowed reference — never free directly | --- ## IDCMP — The Event System **Intuition Direct Communication Message Port** is the core event mechanism. Each window has a `UserPort` (MsgPort) that receives `IntuiMessage` structs: ```mermaid graph LR subgraph "Input Sources" MOUSE["Mouse Move/Click"] KEY["Keyboard"] TIMER["Timer Tick"] RESIZE["Window Resize"] end subgraph "Intuition Dispatch" INT["Intuition
Event Router"] end subgraph "Window IDCMP Port" PORT["Window.UserPort
(MsgPort)"] MSG1["IntuiMessage
Class: MOUSEBUTTONS"] MSG2["IntuiMessage
Class: VANILLAKEY"] MSG3["IntuiMessage
Class: NEWSIZE"] end subgraph "Application" WAIT["Wait(sigmask)"] LOOP["GetMsg() loop"] REPLY["ReplyMsg()"] end MOUSE & KEY & TIMER & RESIZE --> INT INT --> PORT PORT --> MSG1 & MSG2 & MSG3 WAIT --> LOOP LOOP --> REPLY ``` ### Critical IDCMP Classes | Class | Hex | Meaning | |---|---|---| | `CLOSEWINDOW` | `$0200` | User clicked close gadget | | `MOUSEBUTTONS` | `$0008` | Mouse button press/release | | `MOUSEMOVE` | `$0010` | Mouse moved (requires `REPORTMOUSE`) | | `GADGETUP` | `$0040` | Gadget released (RELVERIFY) | | `GADGETDOWN` | `$0020` | Gadget pressed | | `MENUPICK` | `$0100` | Menu item selected | | `VANILLAKEY` | `$00200000` | Cooked keystroke (ASCII) | | `RAWKEY` | `$0400` | Raw keyboard scancode | | `NEWSIZE` | `$0002` | Window resized | | `REFRESHWINDOW` | `$0004` | Damage — app must redraw | | `INTUITICKS` | `$00400000` | ~10Hz timer for UI updates | --- ## Library Interactions — Who Calls Whom ```mermaid graph LR subgraph "Application Code" APP["Your Program"] end subgraph "intuition.library" OS["OpenScreen()"] OW["OpenWindow()"] GT_["GadTools Layout"] SM["SetMenuStrip()"] IDCMP["IDCMP Dispatch"] end subgraph "graphics.library" RP["RastPort Operations
Move, Draw, Text, RectFill"] BM["BitMap Allocation"] VIEW["MakeVPort / LoadView"] end subgraph "layers.library" LY["Layer Clipping
CreateUpfrontLayer"] DMG["Damage List
BeginRefresh / EndRefresh"] end subgraph "exec.library" MP["MsgPort
CreateMsgPort"] SIG["Signals
AllocSignal, Wait"] MEM["Memory
AllocMem, FreeMem"] end APP --> OS & OW & GT_ & SM APP --> RP APP --> MP & SIG OW --> LY OS --> VIEW & BM IDCMP --> MP & SIG RP --> LY LY --> DMG VIEW --> |"Copper list"| COP["Copper DMA"] ``` --- ## Screen Types and Display Pipeline ```mermaid graph TB subgraph "Screens (front to back)" S1["Screen 1: Custom (640×256 4-color)
sc_ViewPort → Copper List 1"] S2["Screen 2: Workbench (640×256 8-color)
sc_ViewPort → Copper List 2"] S3["Screen 3: Game (320×256 32-color)
sc_ViewPort → Copper List 3"] end subgraph "Copper" COP["Copper DMA
Interleaves ViewPorts
Sets palette per screen"] end subgraph "Denise/Lisa" OUT["Video Output
Composited scanlines"] end S1 & S2 & S3 --> COP COP --> OUT ``` The Copper hardware makes Amiga's multi-screen system possible — each screen gets its own palette, resolution, and scroll position, all managed by a single Copper list that switches parameters mid-frame at the correct scanline. --- ## GadTools vs BOOPSI — Gadget Frameworks | Aspect | GadTools (OS 2.0+) | BOOPSI (OS 2.0+) | |---|---|---| | **Philosophy** | Wrapper functions around Intuition gadgets | True OOP with classes, methods, inheritance | | **Creation** | `CreateGadget(kind, prev, newgad, tags)` | `NewObject(class, NULL, tags)` | | **Layout** | Manual X/Y positioning with font scaling | Manual or custom layout classes | | **Event model** | IDCMP `GADGETUP` + `GT_GetIMsg()` | `OM_NOTIFY` → target chain | | **Extensibility** | Fixed set: BUTTON, STRING, SLIDER, etc. | Unlimited custom classes | | **Typical use** | Preferences panels, simple tools | MUI internals, complex UIs | | **Complexity** | Low — 5 functions to learn | High — requires understanding class dispatch | --- ## Refresh Modes — How Windows Repaint | Mode | Flag | Description | Trade-off | |---|---|---|---| | **Simple Refresh** | `WFLG_SIMPLE_REFRESH` | App must redraw on `REFRESHWINDOW` IDCMP | Minimum memory, maximum app work | | **Smart Refresh** | `WFLG_SMART_REFRESH` | Layers saves/restores obscured regions | Uses RAM for damage bitmaps, less app work | | **Super Bitmap** | `WFLG_SUPER_BITMAP` | Full off-screen bitmap, auto-restored | Highest RAM use, zero redraw work | | **Backdrop** | `WFLG_BACKDROP` | Window behind all others, fills screen | Used by Workbench | ```mermaid graph LR subgraph "Simple Refresh" A1["Window obscured"] --> A2["REFRESHWINDOW IDCMP"] A2 --> A3["App: BeginRefresh()"] A3 --> A4["App: Redraw damaged areas"] A4 --> A5["App: EndRefresh()"] end ``` --- ## Common Patterns ### Minimal Window Event Loop ```c struct Window *win = OpenWindowTags(NULL, WA_Title, "My Window", WA_Width, 320, WA_Height, 200, WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_VANILLAKEY, WA_Flags, WFLG_CLOSEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_ACTIVATE, TAG_DONE); BOOL running = TRUE; while (running) { Wait(1L << win->UserPort->mp_SigBit); struct IntuiMessage *msg; while ((msg = GT_GetIMsg(win->UserPort))) { switch (msg->Class) { case IDCMP_CLOSEWINDOW: running = FALSE; break; case IDCMP_VANILLAKEY: /* msg->Code = ASCII key */ break; } GT_ReplyIMsg(msg); } } CloseWindow(win); ``` ### Shared IDCMP Port (Multiple Windows) ```c /* Create one port, share across windows */ struct MsgPort *sharedPort = CreateMsgPort(); win1 = OpenWindowTags(NULL, ..., WA_IDCMP, 0, TAG_DONE); win1->UserPort = sharedPort; ModifyIDCMP(win1, IDCMP_CLOSEWINDOW); win2 = OpenWindowTags(NULL, ..., WA_IDCMP, 0, TAG_DONE); win2->UserPort = sharedPort; ModifyIDCMP(win2, IDCMP_CLOSEWINDOW); /* Single Wait() handles both windows */ /* Check msg->IDCMPWindow to identify source */ ``` --- ## References - RKRM: *Libraries Manual* — Intuition chapter - RKRM: *Libraries Manual* — GadTools chapter - RKRM: *Libraries Manual* — BOOPSI chapter - NDK39: `intuition/intuition.h`, `intuition/screens.h`, `intuition/gadgetclass.h` - ADCD 2.1: Intuition Autodocs — `OpenWindow`, `OpenScreen`, `ModifyIDCMP`