Copyright (c) Hyperion Entertainment and contributors.
Classic Intuition Screens
Contents
Classic Intuition Screens
This sections contains information regarding programming Amiga screens which is no longer in use or apply only to the Classic Amiga platform's ECS/AGA chip set. See Intuition Screens for the current methods used to manipulate Intuition screens.
Screen Data Structures
The Amiga uses color registers and bitplane organization as its internal representation of display data. Screens require a color table and display raster memory for each bitplane. This is the memory where imagery is rendered and later translated by the hardware into the actual video display. This information is contained in data structures from the Amiga's graphics library.
A ViewPort is the main data structure used by the graphics library to represent a screen. Pointers to each of the screen's bitplanes are stored in the graphics library BitMap structure. Color table information is stored in a graphics structure called a ColorMap. And the screen's drawing and font information is stored in the RastPort structure.
The graphics RastPort structure is a general-purpose handle that the graphics library uses for drawing operations. Many Intuition drawing functions also take a RastPort address as a parameter. This makes sense since the RastPort structure contains drawing variables as well as a pointer to the BitMap telling where to draw. See Graphics Primitives chapter for more information on these structures and how they are used.
The Intuition Screen Data Structure
The structures mentioned above are unified along with other information in Intuition's Screen data structure defined in the include file <intuition/screens.h>. Notice that the Screen structure contains instances of a ViewPort, RastPort and BitMap.
struct Screen { struct Screen *NextScreen; struct Window *FirstWindow; WORD LeftEdge, TopEdge, Width, Height; WORD MouseY, MouseX; UWORD Flags; UBYTE *Title, *DefaultTitle; BYTE BarHeight, BarVBorder, BarHBorder, MenuVBorder, MenuHBorder; BYTE WBorTop, WBorLeft, WBorRight, WBorBottom; struct TextAttr *Font; struct ViewPort ViewPort; struct RastPort RastPort; struct BitMap BitMap; struct Layer_Info LayerInfo; struct Gadget *FirstGadget; UBYTE DetailPen, BlockPen; UWORD SaveColor0; struct Layer *BarLayer; UBYTE *ExtData, *UserData; };
In general, applications don't need to access the fields in the Screen structure directly; they use Intuition functions to manipulate the screen instead. Likewise, applications do not set up the Screen themselves; they use one of the OpenScreen() calls (see below). Here is a description of some of the more interesting members of the Screen structure (it is not meant to be a complete description of all the fields).
- LeftEdge, TopEdge
- The LeftEdge and TopEdge variables give the position of the screen relative to the upper left corner of the monitor's visible display (as set by the user in the Overscan preferences editor). If it is positioned down or to the right, the values are positive. If the screen is positioned up or to the left, the values are negative. The values are in screen resolution pixels.
- The screen position may be set when the screen is opened or later by calling the MoveScreen() function.
- Note that the screen's actual display position may not exactly equal the coordinates given in the LeftEdge and TopEdge fields of the Screen structure. This can cause a window which is opened in the visible part of the screen to be incorrectly positioned by a few pixels in each direction. This complication is due to hardware constraints that limit the fineness of screen positioning. For instance, high resolution screens can only be positioned in low resolution pixel coordinates, yet the values in the LeftEdge and TopEdge use high resolution pixel coordinates. So when the screen is displayed, its position is rounded to a position available for the monitor.
- MouseX, MouseY
- Position of the mouse with respect to the upper left corner of the screen.
- ViewPort, RastPort, BitMap, LayerInfo
- Actual instances of the graphics library data structures associated with this screen (not pointers to structures). For normal use of custom screens, these structures may be ignored.
- BarLayer
- A pointer to the Layer structure for the screen's title bar.
- WBorTop, WBorLeft, WBorRight, WBorBottom
- Window border values, see the Intuition Windows for information on pre-calculating the size of window borders for windows that open in this screen.
- Font
- The default screen font, this can be used to pre-calculate the size of the window borders for windows that open in this screen.
- UserData
- Free for application use.
Other Screen structure members provide information on the title bar layer, and attributes of menus and windows opened in the screen. Of particular interest are the values that allow precalculation of window border size. These variables will be discussed in Intuition Windows.
Other Screen Data Structures
In addition to the Screen structure, Intuition uses some other supporting structures defined in the include file <intuition/screens.h> and in <utility/tagitems.h>. (See the SDK for a complete listing.)
Structure Name | Description | Defined in Include File |
---|---|---|
Screen | Main Intuition structure that defines a screen (see above) | <intuition/screens.h> |
DrawInfo | Holds the screen's pen, font and aspect data for Intuition | <intuition/screens.h> |
TagItem | General purpose parameter structure used to set up screens in V36 | <utility/tagitem.h> |
NewScreen | Parameter structure used to create a screen in V34 | <intuition/screens.h> |
ExtNewScreen | An extension to the NewScreen structure used in V37 for backward compatibility with older systems | <intuition/screens.h> |
As previously mentioned, there is an Intuition Screen structure (and a corresponding graphics ViewPort) for every screen in memory. Whenever a new screen is created, Intuition also creates an auxiliary data structure called a DrawInfo.
The DrawInfo structure is similar to a RastPort in that it holds drawing information. But where a RastPort is used at the lower graphics level, the DrawInfo structure is used at the higher Intuition level. Specifically, DrawInfo contains data needed to support the New Look of Intuition. (See the section below, "DrawInfo and the 3D Look" for more information.)
With screens, tag items are used to describe the attributes an application wants for a new, custom screen. Tag items replace the NewScreen structure, the set of parameters used in older versions of the OS to set up a screen.
Applications should use tag items to set up a new screen instead of the NewScreen structure since tag items are often more convenient. For the sake of backwards compatibility, the ExtNewScreen structure is available. ExtNewScreen combines the NewScreen method used to define screens in older versions of the OS with the tag item method. The examples listed in the next section show how these various data structures can be used to set up a new screen.
Custom Screen Functions
All applications require a screen to work in. This can be an existing, public screen or a new, custom screen created by the application itself. To create a new, custom screen to work with, you call OpenScreen().
Creating a new Custom Screen
The old OpenScreen() call relied on a fixed size data structure (NewScreen) which made little allowance for extensions and growth. The new calls are tag based, allowing for the addition of new features without modification of existing structures and applications. The "Screen Attributes" section below contains a complete list of all the tag options available for setting up an Intuition screen. For a general description of tag items, see Utility Library.
The NewScreen structure used with OpenScreen() has been extended with a tag list in V36 to form an ExtNewScreen. This is done by setting the NS_EXTENDED bit in the Type field of the NewScreen structure and adding a pointer to an array of tags to the end of the structure. The NS_EXTENDED bit is ignored in older versions of the operating system, so the tags can be transparently added to existing applications and the features will appear when executed in a system running V36 or greater. See the OpenScreen() Autodocs and the include file <intuition/screens.h> for more information on NS_EXTENDED and the ExtNewScreen structure.
Advanced Screen Programming
This section discusses how to create a dual-playfield Intuition screen and other advanced topics.
Dual-Playfield Screen Example
This example shows how to create a dual-playfield display. Note that this technique is only valid for screen modes which support dual-playfield, do not try to convert other modes.
Setting up dual playfield mode in the OpenScreen() call is not the best method of obtaining a dual playfield viewport for a screen. It is better to open a standard screen, passing to Intuition (or letting Intuition create) only one of the playfield bitmaps (the front one). Next allocate and set up a second bitmap, its bitplanes, and a RasInfo structure installing these into the new screen's viewport. Update the viewport modes to include DUALPF and call MakeScreen() and RethinkDisplay(). This method, shown in the example below, keeps Intuition rendering (gadgets, menus, windows) in a single playfield.
/* dualplayfield.c ** Shows how to turn on dual-playfield mode in a screen. ** ** SAS/C 5.10a ** lc -b1 -cfist -v -y dualplayfield ** blink FROM LIB:c.o dualplayfield.o TO dualplayfield LIB LIB:lc.lib LIB:amiga.lib */ #define INTUI_V36_NAMES_ONLY #include <exec/types.h> #include <exec/memory.h> #include <intuition/intuition.h> #include <graphics/displayinfo.h> #include <clib/exec_protos.h> #include <clib/intuition_protos.h> #include <clib/graphics_protos.h> VOID doDualPF ( struct Window * ); BOOL installDualPF( struct Screen *, struct RastInfo * ); VOID drawSomething( struct RastPort * ); VOID handleIDCMP ( struct Window * ); VOID removeDualPF( struct Screen *s ); struct Library *IntuitionBase; struct Library *GfxBase; VOID main(int argc, char **argv) { struct Window *win; struct Screen *scr; IntuitionBase = OpenLibrary("intuition.library",37); if (IntuitionBase != NULL) { GfxBase = OpenLibrary("graphics.library", 37); if (GfxBase != NULL) { scr = OpenScreenTags(NULL, SA_Depth, 2, SA_DisplayID, HIRES_KEY, SA_Title, "Dual Playfield Test Screen", TAG_END); if ( scr != NULL ) { win = OpenWindowTags(NULL, WA_Title, "Dual Playfield Mode", WA_IDCMP, IDCMP_CLOSEWINDOW, WA_Width, 200, WA_Height, 100, WA_DragBar, TRUE, WA_CloseGadget, TRUE, WA_CustomScreen, scr, TAG_END); if ( win != NULL ) { doDualPF(win); CloseWindow(win); } CloseScreen(scr); } CloseLibrary(GfxBase); } CloseLibrary(IntuitionBase); } } /* ** Allocate all of the stuff required to add dual playfield to a screen. */ VOID doDualPF(struct Window *win) { struct Screen *myscreen; struct RasInfo *rinfo2; struct BitMap *bmap2; struct RastPort *rport2; myscreen = win->WScreen; /* Find the window's screen */ /* Allocate the second playfield's rasinfo, bitmap, and bitplane */ rinfo2 = (struct RasInfo *) AllocMem(sizeof(struct RasInfo), MEMF_PUBLIC | MEMF_CLEAR); if ( rinfo2 != NULL ) { /* Get a rastport, and set it up for rendering into bmap2 */ rport2 = (struct RastPort *) AllocMem(sizeof(struct RastPort), MEMF_PUBLIC ); if (rport2 != NULL ) { bmap2 = (struct BitMap *) AllocMem(sizeof(struct BitMap), MEMF_PUBLIC | MEMF_CLEAR); if (bmap2 != NULL ) { InitBitMap(bmap2, 1, myscreen->Width, myscreen->Height); /* extra playfield will only use one bitplane here. */ bmap2->Planes[0] = (PLANEPTR) AllocRaster(myscreen->Width, myscreen->Height); if (bmap2->Planes[0] != NULL ) { InitRastPort(rport2); rport2->BitMap = rinfo2->BitMap = bmap2; SetRast(rport2, 0); if (installDualPF(myscreen,rinfo2)) { /* Set foreground color; color 9 is color 1 for ** second playfield of hi-res viewport */ SetRGB4(&myscreen->ViewPort, 9, 0, 0xF, 0); drawSomething(rport2); handleIDCMP(win); removeDualPF(myscreen); } FreeRaster(bmap2->Planes[0], myscreen->Width, myscreen->Height); } FreeMem(bmap2, sizeof(struct BitMap)); } FreeMem(rport2, sizeof(struct RastPort)); } FreeMem(rinfo2, sizeof(struct RasInfo)); } } /* ** Manhandle the viewport: ** install second playfield and change modes */ BOOL installDualPF(struct Screen *scrn, struct RastInfo *rinfo2) { ULONG screen_modeID; BOOL return_code = FALSE; screen_modeID = GetVPModeID(&(scrn->ViewPort)); if( screen_modeID != INVALID_ID ) { /* you can only play with the bits in the Modes field ** if the upper half of the screen mode ID is zero!!! */ if ( (screen_modeID & 0xFFFF0000L) == 0L ) { return_code = TRUE; Forbid(); /* Install rinfo for viewport's second playfield */ scrn->ViewPort.RasInfo->Next = rinfo2; scrn->ViewPort.Modes |= DUALPF; Permit(); /* Put viewport change into effect */ MakeScreen(scrn); RethinkDisplay(); } } return(return_code); } /* ** Draw some lines in a rast port...This is used to get some data into ** the second playfield. The windows on the screen will move underneath ** these graphics without disturbing them. */ VOID drawSomething(struct RastPort *rp) { int width, height; int r, c; width = rp->BitMap->BytesPerRow * 8; height = rp->BitMap->Rows; SetAPen(rp, 1); for (r = 0; r < height; r += 40) { for (c = 0; c < width; c += 40) { Move(rp, 0L, r); Draw(rp, c, 0L); } } } /* ** simple event loop to wait for the user to hit the close gadget ** on the window. */ VOID handleIDCMP(struct Window *win) { BOOL done = FALSE; struct IntuiMessage *message = NULL; ULONG class; ULONG signals; while (!done) { signals = Wait(1L << win->UserPort->mp_SigBit); if (signals & (1L << win->UserPort->mp_SigBit)) { while ((!done) && (message = (struct IntuiMessage *)GetMsg(win->UserPort))) { class = message->Class; ReplyMsg((struct Message *)message); switch (class) { case IDCMP_CLOSEWINDOW: done = TRUE; break; } } } } } /* ** remove the effects of installDualPF(). ** only call if installDualPF() succeeded. */ VOID removeDualPF(struct Screen *scrn) { Forbid(); scrn->ViewPort.RasInfo->Next = NULL; scrn->ViewPort.Modes &= ~DUALPF; Permit(); MakeScreen(scrn); RethinkDisplay(); }