Intuition V47 BOOPSI and Input Extensions¶
intuition.library V47 (AmigaOS 3.2) adds a set of input and BOOPSI extensions that let applications and gadget classes take part in mouse-wheel scrolling, hover-driven mouse pointers and tooltips, and hidden gadgets without patching the system. This article collects these additions from the 3.2 NDK headers (intuition/intuition.h, gadgetclass.h, imageclass.h, pointerclass.h, screens.h) and the intuition release notes, together with the smaller V45–V47 changes a programmer is likely to meet: hidden windows, built-in pointer types, new frame and system images, and the DrawInfo revision.
Everything here requires intuition.library 47 or later unless a different version is stated. Check IntuitionBase->LibNode.lib_Version (or open the library with version 47) before relying on any of it; on older systems the tags are ignored and the methods are never sent.
At a glance¶
| Addition | Kind | Value | Version |
|---|---|---|---|
IDCMP_EXTENDEDMOUSE 3.2+ |
IDCMP class | 0x08000000 |
V47 |
struct IntuiWheelData |
message payload | INTUIWHEELDATA_VERSION = 2 |
V47 |
IMSGCODE_INTUIWHEELDATA |
IntuiMessage.Code |
1<<15 |
V47 |
GM_HANDLESCROLL 3.2+ |
gadget method | 14 |
V47 |
GM_QUERYHOVERED 3.2+ |
gadget method | 15 |
V47 |
GA_Hidden 3.2+ |
gadgetclass attr | GA_Dummy+54 |
V47 |
GA_PointerType 3.2+ |
gadgetclass attr | GA_Dummy+61 |
V47 |
GA_ParentHidden 3.2+ |
gadgetclass attr | GA_Dummy+62 |
V47 |
GMORE_HIDDEN 3.2+ |
ExtGadget.MoreFlags |
0x00000010 |
V47 |
GMORE_BOOPSIGADGET 3.2+ |
ExtGadget.MoreFlags |
0x00000400 |
V47 |
GMORE_FREEIMAGE 3.2+ |
ExtGadget.MoreFlags |
0x00000800 |
V47 |
GMORE_PARENTHIDDEN 3.2+ |
ExtGadget.MoreFlags |
0x01000000 |
V47 |
WA_Hidden 3.2+ |
window tag | WA_Dummy+0x3c |
V47 |
WA_PointerType 3.2+ |
window tag | WA_Dummy+0x50 |
V47 |
WA_IconifyGadget 3.1.4+ |
window tag | WA_Dummy+0x60 |
V46 |
ShowWindow() / HideWindow() |
functions | — | V46 |
PGA_KnobImage 3.2+ |
propgclass attr | PGA_Dummy+0x000D |
V47 |
Mouse wheel: IDCMP_EXTENDEDMOUSE¶
Intuition 47.26 introduced "true OS level support for scrollwheel". A window that wants raw wheel events adds IDCMP_EXTENDEDMOUSE to its IDCMP flags. Each event arrives as an IntuiMessage whose Class is IDCMP_EXTENDEDMOUSE and whose IAddress points to:
struct IntuiWheelData
{
UWORD Version; /* version of this structure (see below) */
UWORD Reserved; /* always 0, reserved for future use */
WORD WheelX; /* horizontal wheel movement delta */
WORD WheelY; /* vertical wheel movement delta */
struct Gadget *HoveredGadget; /* Version 2: pointer to gadget that is hovered */
};
#define INTUIWHEELDATA_VERSION 2 /* current version of the structure above */
enum
{
IMSGCODE_INTUIWHEELDATA = (1<<15),
IMSGCODE_INTUIRAWKEYDATA = (1<<14),
IMSGCODE_INTUIWHEELDATAREJECT = (1<<13) /* for internal use */
};
Rules from the header comment:
- Always check
CodeagainstIMSGCODE_INTUIWHEELDATAbefore treatingIAddressas anIntuiWheelData. Future versions of Intuition may send other structures with the same class. - Check
Versionbefore reading fields.HoveredGadgetonly exists from version 2. IMSGCODE_INTUIWHEELDATAREJECTis reserved for Intuition's internal use. Do not send or interpret it.IAddressbelongs to Intuition. Copy what you need beforeReplyMsg().
Who gets the wheel event¶
The release notes describe several delivery paths, added over 47.26–47.50:
- BOOPSI gadgets under the pointer can receive
GM_HANDLESCROLL(see below). In ReAction,layout.gadgetpasses it to "the child under the mouse", andscroller.gadget,listbrowser.gadgetandtexteditor.gadgetimplement it. - GadTools 47.6 added the same OS-level wheel support for its own gadgets.
- As a fallback (47.46), Intuition sends wheel events to the nearest vertical scrollbar in the window when none of the newer mechanisms handled them.
- MUI windows are excluded from this treatment (47.46). They receive the event and do their own thing.
- The new wheel handling filters out legacy NewMouse
IDCMP_RAWKEYwheel codes. 47.50 added a private mechanism to let selected programs (AWeb is the example given) keep getting them.
The NewMouse raw key codes are in libraries/keymap.h: RAWKEY_WHEEL_UP (0x7A), RAWKEY_WHEEL_DOWN (0x7B), RAWKEY_WHEEL_LEFT (0x7C) and RAWKEY_WHEEL_RIGHT (0x7D), with the comment "aka NM_WHEEL_*". A program that must also run on intuition.library before V47 handles both: IDCMP_EXTENDEDMOUSE on V47, and IDCMP_RAWKEY with these codes on older systems. Workbench 47.29 does the same thing: it uses IDCMP_EXTENDEDMOUSE and keeps the NewMouse IDCMP_RAWKEY path for intuition before V47.
Example: a wheel-aware window¶
This minimal program opens a window, counts wheel steps and shows how to switch the pointer with WA_PointerType while the window is "busy". It follows the NDK prototypes (OpenWindowTags(), SetWindowPointer()), and needs intuition.library 47.
#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/pointerclass.h>
#include <libraries/keymap.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
struct IntuitionBase *IntuitionBase;
int main(void)
{
struct Window *win;
LONG posx = 0, posy = 0;
BOOL done = FALSE;
IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 47);
if (IntuitionBase == NULL)
{
PutStr("Needs intuition.library V47\n");
return 20;
}
win = OpenWindowTags(NULL,
WA_Title, "Wheel test",
WA_Width, 320,
WA_Height, 100,
WA_DragBar, TRUE,
WA_DepthGadget, TRUE,
WA_CloseGadget, TRUE,
WA_Activate, TRUE,
WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_EXTENDEDMOUSE |
IDCMP_RAWKEY,
WA_PointerType, POINTERTYPE_CROSS, /* built-in pointer */
TAG_DONE);
if (win)
{
while (!done)
{
struct IntuiMessage *imsg;
WaitPort(win->UserPort);
while ((imsg = (struct IntuiMessage *)GetMsg(win->UserPort)))
{
ULONG class = imsg->Class;
UWORD code = imsg->Code;
WORD dx = 0, dy = 0;
if (class == IDCMP_EXTENDEDMOUSE &&
code == IMSGCODE_INTUIWHEELDATA)
{
struct IntuiWheelData *wd = imsg->IAddress;
/* copy before replying: IAddress belongs to Intuition */
dx = wd->WheelX;
dy = wd->WheelY;
}
ReplyMsg((struct Message *)imsg);
switch (class)
{
case IDCMP_CLOSEWINDOW:
done = TRUE;
break;
case IDCMP_EXTENDEDMOUSE:
posx += dx;
posy += dy;
Printf("wheel dx=%ld dy=%ld -> %ld,%ld\n",
(LONG)dx, (LONG)dy, posx, posy);
break;
case IDCMP_RAWKEY:
/* legacy NewMouse codes, only seen on pre-V47
Intuition or programs exempted from filtering */
if (code == RAWKEY_WHEEL_UP) posy--;
if (code == RAWKEY_WHEEL_DOWN) posy++;
break;
}
}
/* show the busy pointer while "working", then restore */
SetWindowPointer(win, WA_PointerType, POINTERTYPE_BUSY, TAG_DONE);
Delay(5);
SetWindowPointer(win, WA_PointerType, POINTERTYPE_CROSS, TAG_DONE);
}
CloseWindow(win);
}
CloseLibrary((struct Library *)IntuitionBase);
return 0;
}
Printf() here is the dos.library function, so %ld arguments must be LONG.
GM_HANDLESCROLL — wheel input for gadgets¶
#define GM_HANDLESCROLL (14)
/* Handle a mouse wheel event. msg is struct gpInput *
* return GMR_REUSE or GMR_NOREUSE */
The message is the ordinary struct gpInput used by GM_GOACTIVE/GM_HANDLEINPUT, and the method returns one of the GMR_REUSE / GMR_NOREUSE codes (1<<2 / 1<<1). A class that does not know the method must pass it to its superclass, as with every unknown method, so that the default behaviour is kept.
Composite gadgets should forward the method to the child under the pointer, as layout.gadget does. The ReAction scroller (47.13) implements it and since 47.16 scrolls "3 times delta but no more than quarter page, and no less than 1 delta" per event, which is a reasonable policy for custom scrollable classes as well.
GM_QUERYHOVERED — hover queries, pointers and tooltips¶
#define GM_QUERYHOVERED (15)
/* query the (sub) gadget that was last hovered (aka responded to HELPTEST)
* apart from propagating to sub gadgets it is basically an OM_GET
*/
Intuition 47.32 added this method and uses it "to figure out what mousepointer to show". window.class 47.15 uses it to implement ReAction tooltips, which removed its old dangling pointers to gadgets and strings. layout.gadget (47.24) and clicktab.gadget implement it. clicktab only propagates it to its page when the page is hovered.
So GM_QUERYHOVERED works like an attribute query that is routed to the sub-gadget which last answered GM_HELPTEST. A leaf gadget answers it like OM_GET; a composite gadget passes it down to the hovered child. A sketch of the composite case:
case GM_QUERYHOVERED:
/* data->hovered was remembered in our GM_HELPTEST handler */
if (data->hovered)
return DoMethodA(data->hovered, msg);
return DoSuperMethodA(cl, obj, msg);
Remember the hovered child in GM_HELPTEST, because that is the test the comment refers to. Intuition only calls this method on real BOOPSI gadgets. Several 47.x fixes dealt with crashes when non-BOOPSI or GadTools gadgets were hovered, and since 47.41 Intuition uses GMORE_BOOPSIGADGET to tell them apart.
GA_PointerType and WA_PointerType¶
GA_PointerType (GA_Dummy+61, V47) selects a built-in pointer to show while the gadget is hovered. WA_PointerType (WA_Dummy+0x50, added in 47.34) does the same for a whole window. It is accepted by OpenWindowTagList() and SetWindowPointerA(); zero is the default pointer. The constants live in intuition/pointerclass.h. Pointer preferences support "40 different standard pointertypes":
| Value | Name | Use |
|---|---|---|
| 0 | POINTERTYPE_NORMAL |
normal pointer |
| 1 | POINTERTYPE_BUSY |
busy |
| 2 | POINTERTYPE_ALIAS |
dragging to create a reference/virtual copy |
| 3 | POINTERTYPE_CELL |
over a table cell |
| 4 | POINTERTYPE_COLUMNRESIZE |
column can be / is being resized |
| 5 | POINTERTYPE_CONTEXTMENU |
a context menu can be opened here |
| 6 | POINTERTYPE_COPY |
drag & drop will copy |
| 7 | POINTERTYPE_CROSS |
precise selection / drawing |
| 8 | POINTERTYPE_DRAGANDDROP |
item being dragged |
| 9 | POINTERTYPE_EASTRESIZE |
resizable on the right border |
| 10 | POINTERTYPE_EASTWESTRESIZE |
being resized left/right |
| 11 | POINTERTYPE_HAND |
item is draggable/movable |
| 12 | POINTERTYPE_HELP |
help available |
| 13 | POINTERTYPE_LINK |
hyperlink / tab |
| 14 | POINTERTYPE_MENU |
a menu is active |
| 15 | POINTERTYPE_NODROP |
cannot drop here |
| 16 | POINTERTYPE_NONE |
pointer deactivated |
| 17–22 | POINTERTYPE_NORTHEASTRESIZE, …NORTHEASTSOUTHWESTRESIZE, …NORTHRESIZE, …NORTHSOUTHRESIZE, …NORTHWESTRESIZE, …NORTHWESTSOUTHEASTRESIZE |
resize directions |
| 23 | POINTERTYPE_NOTALLOWED |
operation not allowed |
| 24 | POINTERTYPE_PROGRESS |
working, but input still accepted |
| 25 | POINTERTYPE_ROWRESIZE |
row resize |
| 26 | POINTERTYPE_SCROLLALL |
item can be / is being moved |
| 27–29 | POINTERTYPE_SOUTHEASTRESIZE, …SOUTHRESIZE, …SOUTHWESTRESIZE |
resize directions |
| 30 | POINTERTYPE_TEXT |
horizontal text selectable |
| 31 | POINTERTYPE_VERTICALTEXT |
vertical text selectable |
| 32 | POINTERTYPE_WESTRESIZE |
resizable on the left border |
| 33 | POINTERTYPE_ZOOMIN |
click zooms in |
| 34 | POINTERTYPE_ZOOMOUT |
click zooms out |
| 35 | POINTERTYPE_PEN |
drawing action |
| 36 | POINTERTYPE_ROTATE |
rotate |
| 37 | POINTERTYPE_RUBBER |
erasing action |
| 38 | POINTERTYPE_SELECT |
select |
| 39 | POINTERTYPE_SMUDGE |
smudge |
| 40 | POINTERTYPE_COUNT |
number of types |
GA_PointerType and WA_PointerType sit next to the V39 tags WA_BusyPointer and WA_PointerDelay, which are still the right way to show a deferred busy pointer. Intuition 47.24 also stopped choking on pointer types with a negative id coming from IPrefs.
Hidden gadgets: GA_Hidden and GA_ParentHidden¶
| Attribute | Meaning |
|---|---|
GA_Hidden (BOOL) |
On set, maps to GMORE_HIDDEN. On get, returns GMORE_HIDDEN | GMORE_PARENTHIDDEN, so it is TRUE when the gadget is hidden for either reason. |
GA_ParentHidden (BOOL) |
Sets GMORE_PARENTHIDDEN on the gadget and, recursively, on all children. |
Both arrived in intuition 47.29. Composite gadgets must implement the recursion themselves; the header notes that "V47 page, layout and clicktab gadgets all recurse". Hiding is cooperative. The layout gadget release note (47.22) says hidden gadgets now "have the chance to not render themselves (it requires cooperation from every single gadget)". scroller.gadget 47.15 checks both flags before painting. A custom class should test GMORE_HIDDEN | GMORE_PARENTHIDDEN in its GM_RENDER and draw nothing when either is set.
Up to 47.45, GA_ParentHidden could be set but not read, and GA_ReadOnly read but not set. Both are fixed in 47.45, so do not rely on reading GA_ParentHidden from older 47.x builds.
New ExtGadget MoreFlags¶
| Flag | Value | Meaning |
|---|---|---|
GMORE_HIDDEN 3.2+ |
0x00000010 |
gadget is explicitly hidden and cannot be drawn |
GMORE_BOOPSIGADGET 3.2+ |
0x00000400 |
gadget was (sub-)instantiated from gadgetclass |
GMORE_FREEIMAGE 3.2+ |
0x00000800 |
gadgetclass frees the gadget's GA_Image on OM_DISPOSE |
GMORE_PARENTHIDDEN 3.2+ |
0x01000000 |
a parent is hidden, so this gadget is implicitly hidden |
GMORE_BOOPSIGADGET (47.39) is set on every instance of gadgetclass or its subclasses. Both real BOOPSI gadgets and old-style custom gadgets have type GTYP_CUSTOMGADGET, so this flag is now the safe way to tell whether you may send BOOPSI methods to a gadget found in a window's list:
struct ExtGadget *eg = (struct ExtGadget *)gad;
if ((eg->Flags & GFLG_EXTENDED) && (eg->MoreFlags & GMORE_BOOPSIGADGET))
{
/* safe to DoGadgetMethod() / GetAttr() on it */
}
GMORE_FREEIMAGE (47.39) asks gadgetclass to dispose of the gadget's render image automatically. The release note warns: "Do not use this flag with gadget classes that already free their images themselves!"
Windows: WA_Hidden, ShowWindow, HideWindow, iconify¶
WA_Hidden(BOOL, 47.50): open the window already hidden.HideWindow(win)/ShowWindow(win, other)(V46): the SFD prototypes areBOOL ShowWindow(struct Window *window, struct Window *other)andBOOL HideWindow(struct Window *window). Forother, pass another window to place this one in front of it,NULL(WINDOW_BACKMOST) to place it behind all windows of the same type, orWINDOW_FRONTMOST((struct Window *)1). Neither call takes effect immediately. Intuition applies the change the next time it handles an input event, at 10 to 60 times a second.IDCMP_CHANGEWINDOWreportsCWCODE_HIDE(0x0002) andCWCODE_SHOW(0x0003) for these state changes (V46).WA_IconifyGadget(V46): adds an iconify gadget (GTYP_ICONIFY=0x0090, imageICONIFYIMAGE). Pressing it sendsIDCMP_CLOSEWINDOWwithCode= 1 instead of 0.WFLG_HASICONIFY(0x40000000) marks such windows.- Automatic placement (V47): if a window gives neither
WA_LeftnorWA_Topand setsWA_AutoAdjust, Intuition centres its title bar under the mouse pointer.
Images and frames¶
sysiclass¶
New SYSIA_Which values in imageclass.h:
| Constant | Value | Image |
|---|---|---|
ICONIFYIMAGE 3.2+ |
0x16 |
window iconify gadget |
MENUMX 3.2+ |
0x1B |
menu mutual-exclude ("radio") mark |
MENUSUB 3.2+ |
0x1C |
sub-menu indicator |
SHIFTKEYIMAGE 3.2+ |
0x2A |
Shift-key symbol in menus |
Leaving out SYSIA_DrawInfo no longer crashes (47.39); you get a monochrome image instead, which is a hint that something is missing. IA_EraseBackground (BOOL, IA_Dummy+0x2D, OM_SET only on sysiclass) set to FALSE blits irregular images through a mask instead of clearing their whole rectangle. For now only MXIMAGE honours it.
The release notes say several of these constants were renumbered in 47.28, before 3.2 went public, to avoid clashes (FRAME_CONTEXT, MXMENUIMAGE (renamed MENUMX), SHIFTKEYIMAGE, MIF_SHIFTCOMMSEQ, MIF_COMMSEQEXTPARSE). Always build against the final 3.2 NDK headers.
frameiclass¶
IA_FrameType 3.0+ |
Value | Look |
|---|---|---|
FRAME_DEFAULT 3.1+ |
0 | thin V37 frame |
FRAME_BUTTON 3.1+ |
1 | button frame |
FRAME_RIDGE 3.1+ |
2 | string-gadget ridge |
FRAME_ICONDROPBOX 3.1+ |
3 | AppWindow drop area |
FRAME_PROPBORDER 3.2+ |
4 | proportional gadget container (V47) |
FRAME_PROPKNOB 3.2+ |
5 | proportional gadget knob (V47) |
FRAME_DISPLAY 3.2+ |
6 | recessed read-only display (V47) |
FRAME_CONTEXT 3.2+ |
7 | context frame with headline (V47) |
New image attributes for V47:
| Attribute | Value | Type | Notes |
|---|---|---|---|
IA_Orientation 3.2+ |
IA_Dummy+0x23 |
UBYTE | 0 horizontal, 1 vertical; for FRAME_PROPKNOB and subclasses |
IA_Label 3.2+ |
IA_Dummy+0x28 |
STRPTR | headline text of a FRAME_CONTEXT frame |
IA_EraseBackground 3.2+ |
IA_Dummy+0x2D |
BOOL | see sysiclass above |
IA_LabelPen 3.2+ |
IA_Dummy+0x38 |
UWORD | colour of the label |
In 47.47 the FRAME_CONTEXT headline moved from IA_Data/IA_FGPen to IA_Label/IA_LabelPen, because existing software (gadtools among them) already used the old attributes for other things. gadtools.library 47.13 or later is needed for headlines in GadTools bevel boxes. IA_FrameType is now gettable. The new IM_FRAMEBOX flag FRAMEF_MINIMAL (1<<1) returns only the edge sizes without padding.
Proportional gadgets with BOOPSI knobs¶
The new PropInfo flag SMARTKNOBIMAGE (0x0020) tells Intuition that a custom knob is a BOOPSI image supporting IM_DRAWFRAME, so it can be resized automatically (47.44). For propgclass, PGA_KnobImage sets the image and the flag at once. PGA_Top, PGA_Total and PGA_Visible accept full 32-bit values since 47.39.
Screens and DrawInfo¶
DRI_VERSION3 (V47) addsdri_Screen, a back pointer to the screen, and penBARCONTOURPEN(0x000C), raisingNUMDRIPENSto 13.BARCONTOURPENdraws the left/top edges of the screen bar and menus, andBARTRIMPENthen draws right/bottom, for an embossed look. SettingBARCONTOURPENequal toBARBLOCKPENgives the V39 look. Checkdri_Version >= 3before reading either.SA_OffScreenDragging(SA_Dummy+0x2a, V45): windows may be dragged partly off the screen. It defaults to TRUE for Workbench (subject to IControl prefs) and FALSE elsewhere.OSERR_NORTGBITMAP(10): the RTG software could not allocate the screen bitmap.OpenScreenTagList()limits the requested depth to 8 for hicolor and truecolor screens as well (47.36).
Menus¶
SUBMENU(0x0200, MenuItem flag): draw the standard sub-menu mark (theMENUSUBimage). GadTools 47.8 sets it instead of using the » character.MIF_SHIFTCOMMSEQ(0x0800): the shortcut needs Shift. It is drawn with a Shift symbol and takes precedence, so Shift+Amiga+S and Amiga+S can be different items. From 47.49 it also applies to non-COMMSEQstrings.- Mutually exclusive items are drawn as radio buttons on new-look screens (47.11).
IntuitionControlA¶
ULONG IntuitionControlA(APTR object, CONST struct TagItem *taglist) was added in 47.28 as a multi-purpose control call. Its tag base is ICTRL_Dummy (TAG_USER + 0x1C000), and the header states "No public tags defined so far". IPrefs uses it to install GUI support hooks such as border-gadget rearrangement and the GUI exception list. Applications have no public use for it.
Writing classes that degrade on V40¶
- Unknown methods (14, 15) and unknown attributes fall through to the superclass. On older Intuition they are never sent, so supporting them costs nothing.
- Test
GMORE_HIDDEN | GMORE_PARENTHIDDENonly throughGFLG_EXTENDEDgadgets, sinceMoreFlagsexists only instruct ExtGadget. - Read
IntuiWheelData.HoveredGadgetonly whenVersion >= 2. - Ask for both
IDCMP_EXTENDEDMOUSEandIDCMP_RAWKEYif you must handle wheels on old and new systems alike.
See Also¶
- Intuition Library Reference
- Intuition Windows, Screens, and the Event Loop
- intuition.library function reference
- Intuition Gadgets
- GadTools V47 Additions
- ReAction GUI Toolkit
- AmigaOS 3.2 — What Changed for Developers
Sources: NDK 3.2 R4 Include_H/intuition/{intuition.h,gadgetclass.h,imageclass.h,pointerclass.h,screens.h}, Include_H/libraries/keymap.h, SFD/intuition_lib.sfd, Autodocs/intuition.doc, Autodocs/layout_gc.doc, ReleaseNotes/{intuition,layout,window,scroller,clicktab,gadtools,wb,Pointer}-RelNotes Updated: 2026-11-13