Copyright (c) Hyperion Entertainment and contributors.

Window Structures and Functions

From AmigaOS Documentation Wiki
Jump to navigation Jump to search

Basic Window Structures and Functions

This section introduces the basic data structures and functions an application uses to create an Intuition window. Intuition uses the Window data structure defined in <intuition/intuition.h> to represent windows. Most of Intuition's window functions use this structure in some way. Other related structures used to create and operate windows are summarized in the following Table:

Structure Name Description Defined in Include File
Window Main Intuition structure that defines a window <intuition/intuition.h>
TagItem General purpose parameter structure used to set up windows in V37 <utility/tagitem.h>
NewWindow Parameter structure used to create a window in V34 <intuition/intuition.h>
ExtNewWindow An extension to the NewWindow structure used in V37 for backward compatibility with older systems <intuition/intuition.h>
Layer A drawing rectangle that clips graphic operations falling within its boundaries <graphics/clip.h>
RastPort General purpose handle used for graphics library drawing operations. <graphics/rastport.h>

Intuition's window system relies on the layers library and graphics library to implement many of its features. The Window structure is closely related to the Layer structure defined in <graphics/clip.h> and the RastPort structure defined in <graphics/rastport.h>. The system uses these structures to store drawing state data. In general, applications don't have to worry about the internal details of these structures but use them instead as convenient handles, passing them as arguments to lower-level functions. See the Layers Library and Graphics Primitives for more information.

The Window Structure

The Window structure is the main Intuition data structure used to represent a window. For the most part, applications treat this structure only as a handle. Window operations are performed by calling system functions that take Window as an argument instead of directly manipulating fields within the structure. However, there are some useful variables in a Window structure which are discussed in this section.

struct Window
    {
    struct Window *NextWindow;
    WORD LeftEdge, TopEdge, Width, Height;
    WORD MouseY, MouseX;
    WORD MinWidth, MinHeight;
    UWORD MaxWidth, MaxHeight;
    ULONG Flags;
    struct Menu *MenuStrip;
    UBYTE *Title;
    struct Requester *FirstRequest, *DMRequest;
    WORD ReqCount;
    struct Screen *WScreen;
    struct RastPort *RPort;
    BYTE BorderLeft, BorderTop, BorderRight, BorderBottom;
    struct RastPort *BorderRPort;
    struct Gadget *FirstGadget;
    struct Window *Parent, *Descendant;
    UWORD *Pointer;
    BYTE PtrHeight, PtrWidth;
    BYTE XOffset, YOffset;
    ULONG IDCMPFlags;
    struct MsgPort *UserPort, *WindowPort;
    struct IntuiMessage *MessageKey;
    UBYTE DetailPen, BlockPen;
    struct Image *CheckMark;
    UBYTE *ScreenTitle;
    WORD GZZMouseX, GZZMouseY, GZZWidth, GZZHeight;
    UBYTE *ExtData;
    BYTE *UserData;
    struct Layer *WLayer;
    struct TextFont *IFont;
    ULONG MoreFlags;
    };
LeftEdge, TopEdge, Width and Height
These variables reflect current position and size of the window. If the user sizes or positions the window, then these values will change. The position of the window is relative to the upper left corner of the screen.
MouseX, MouseY, GZZMouseX, GZZMouseY
The current position of the Intuition pointer with respect to the window, whether or not this window is currently the active one. For GimmeZeroZero windows, the GZZ variables reflect the position relative to the inner layer (see "Window Types" below). For normal windows, the GZZ variables reflect the position relative to the window origin after taking the borders into account.
ReqCount
Contains a count of the number of requesters currently displayed in the window. Do not rely on the value in this field, instead use IDCMP_REQSET and IDCMP_REQCLEAR to indirectly determine the number of open requesters in the window.
WScreen
A pointer to the Screen structure of the screen on which this window was opened.
RPort
A pointer to this window's RastPort structure. Use this RastPort pointer to render into your window with Intuition or graphics library rendering functions.
BorderLeft, BorderTop, BorderRight, BorderBottom
These variables describe the actual size of the window borders. The border size is not changed after the window is opened.
BorderRPort
With GimmeZeroZero windows, this variable points to the RastPort for the outer layer, in which the border gadgets are kept.
UserData
This pointer is available for application use. The program can attach a data block to this window by setting this variable to point to the data.

For a commented listing of the Window structure see <intuition/intuition.h> in the SDK.

Window Attributes

This section discusses all window attributes. As mentioned earlier, a window's attributes may be specified with either TagItems, NewWindow or ExtNewWindow depending on how the window is opened.

Attributes are listed here by their TagItem ID name (TagItem.ti_Tag). For each tag item, the equivalent field setting in the NewWindow structure is also listed if it exists. Some window attributes specified with tags have no NewWindow equivalent.

Extended New Window

Of the three functions for opening a window, only OpenWindow() is present in all versions of the OS. This function takes a NewWindow structure as its sole argument. In order to allow applications to use the OpenWindow() call with TagItem attributes, an extended version of the NewWindow structure has been created named ExtNewWindow.

Setting WFLG_NW_EXTENDED in the NewWindow.Flags field specifies to the OpenWindow() call that this NewWindow structure is really an ExtNewWindow structure. This is simply a standard NewWindow structure with a pointer to a tag list at the end. Since WFLG_NW_EXTENDED is ignored prior to V36, information provided in the tag list will be ignored by earlier versions of Intuition. Note that WFLG_NW_EXTENDED may not be specified in the WA_Flags tag.

Window Attribute Tags

WA_Left, WA_Top, WA_Width and WA_Height
Describe where the window will first appear on the screen and how large it will be initially. These dimensions are relative to the top left corner of the screen, which has the coordinates (0,0).
WA_Left is the initial x position, or offset, from the left edge of the screen. The leftmost pixel is pixel 0, and values increase to the right. Equivalent to NewWindow.LeftEdge.
WA_Top is the initial y position, or offset, from the top edge of the screen. The topmost pixel is pixel 0, and values increase to the bottom. Equivalent to NewWindow.TopEdge.
WA_Width is the initial window width in pixels. This Tag is equivalent to NewWindow.Width.
WA_Height is the initial window height in lines. This Tag is equivalent to NewWindow.Height.
WA_DetailPen and WA_BlockPen
WA_DetailPen specifies the pen number for the rendering of window details like gadgets or text in the title bar. WA_BlockPen specifies the pen number for window block fills, like the title bar. These pens are also used for rendering menus. Equivalent to NewWindow.DetailPen and NewWindow.BlockPen.
The specific color associated with each pen number depends on the screen. Specifying -1 for these values sets the window's detail and block pen the same as the screen's detail and block pen.
Detail pen and block pen have largely been replaced starting with V36 by the pen array in the DrawInfo structure. See the section on "DrawInfo and the 3D Look" in Intuition Screens for more information.
WA_IDCMP
IDCMP flags tell Intuition what user input events the application wants to be notified about. The IDCMP flags are listed and described in the OpenWindowTagList() description in the SDK and in Intuition Input and Output Methods. Equivalent to NewWindow.IDCMPFlags.
If any of these flags are set, Intuition creates a pair of message ports for the window (one internal to Intuition and one used by the application). These ports are for handling messages about user input events. If WA_IDCMP is NULL or unspecified, no IDCMP is created for this window.
The ModifyIDCMP() function can be used to change the window's IDCMP flags after it is open.
WA_Gadgets
A pointer to the first in the linked list of Gadget structures that are to be included in this window. These gadgets are application gadgets, not system gadgets. See Intuition Gadgets for more information. Equivalent to NewWindow.FirstGadget.
WA_Checkmark
A pointer to an Image structure, which is to be used as the checkmark image in this window's menus. To use the default checkmark, do not specify this tag or set this field to NULL. Equivalent to NewWindow.CheckMark.
WA_Title
A pointer to a NULL terminated text string, which is used as the window title and is displayed in the window's title bar.
Intuition draws the text using the colors defined in the DrawInfo pen array (DrawInfo.dri_Pens) and displays as much as possible of the window title, depending upon the current width of the title bar. Equivalent to NewWindow.Title. See "DrawInfo and the 3D Look" in Intuition Screens for more information on the pen array.
The title is rendered in the screen's default font.
A title bar is added to the window if any of the properties WA_DragBar (WFLG_WINDOWDRAG), WA_DepthGadget (WFLG_WINDOWDEPTH), WA_CloseGadget (WFLG_WINDOWCLOSE) or WA_Zoom are specified, or if text is specified for a window title. If no text is provided for the title, but one or more of these system gadgets are specified, the title bar will be blank. Equivalent to NewWindow.Title.
WA_ScreenTitle
A pointer to a NULL terminated text string, which is used as the screen title and is displayed, when the window is active, in the screen's title bar. After the screen has been opened the screen's title may be changed by calling SetWindowTitles() (which is the only method of setting the window's screen title prior to V36).
WA_CustomScreen
A pointer to the Screen structure of a screen created by this application. The window will be opened on this screen. The custom screen must already be opened when the OpenWindowTagList() call is made. Equivalent to NewWindow.Screen, also implies NewWindow.Type of CUSTOMSCREEN.
WA_MinWidth, WA_MinHeight, WA_MaxWidth and WA_MaxHeight
These tags set the minimum and maximum values to which the user may size the window. If the flag WFLG_WINDOWSIZING is not set, then these variables are ignored. Values are measured in pixels. Use (~0) for the WA_MaxWidth (WA_MaxHeight) to allow for a window as wide (tall) as the screen. This is the complete screen, not the visible part or display clip.
Setting any of these variables to 0, will take the setting for that dimension from its initial value. For example, setting MinWidth to 0, will make the minimum width of this window equal to the initial width of the window.
Equivalent to NewWindow.MinWidth, NewWindow.MinHeight, NewWindow.MaxWidth and NewWindow.MaxHeight. Use the WindowLimits() function to change window size limits after the window is opened.
WA_InnerWidth and WA_InnerHeight
Specify the dimensions of the interior region of the window, i.e., inside the border, independent of the border widths. When using WA_InnerWidth and WA_InnerHeight an application will probably want to set WA_AutoAdjust (see below).
WA_PubScreen
Open the window as a visitor window on the public screen whose address is in the ti_Data field of the WA_PubScreen TagItem. To ensure that this screen remains open until OpenWindowTagList() has completed, the application must either be the screen's owner, have a window open on the screen, or use LockPubScreen(). Setting this tag implies screen type of PUBLICSCREEN.
WA_PubScreenName
Declares that the window is to be opened as a visitor on the public screen whose name is pointed to by the ti_Data field of the WA_PubScreenName TagItem. The OpenWindowTagList() call will fail if it cannot obtain a lock on the named public screen and no fall back name (WA_PubScreenFallBack) is specified. Setting this tag implies screen type of PUBLICSCREEN.
WA_PubScreenFallBack
A Boolean, specifies whether a visitor window should "fall back" to the default public screen (or Workbench) if the named public screen isn't available This tag is only meaningful when used in conjunction with WA_PubScreenName.
WA_Zoom
Pointer to an array of four WORDs, the initial LeftEdge, TopEdge, Width and Height values for the alternate zoom position and size. It also specifies that the application wants a zoom gadget for the window, whether or not it has a sizing gadget.
A zoom gadget is always supplied to a window if it has both depth and sizing gadgets. This tag allows the application to open a window with a zoom gadget when the window does not have both the depth and sizing gadgets.
WA_MouseQueue
An initial value for the mouse message backlog limit for this window. The SetMouseQueue() function will change this limit after the window is opened.
WA_RptQueue
An initial value of repeat key backlog limit for this window.
WA_NewLookMenus
Indicates that the window should use 3D menus or not. Defaults to FALSE for compatibility.

Boolean Window Attribute Tags

These boolean window tags are alternatives to the NewWindow.Flags bit fields with similar names. Unlike the tags discussed above, the ti_Data field of these TagItems is set to either TRUE or FALSE.

WA_SizeGadget
Specifying this flag tells Intuition to add a sizing gadget to the window. Intuition places the sizing gadget in the lower right corner of the window. By default, the right border is adjusted to accommodate the sizing gadget, but the application can specify one of the following two flags to change this behavior. The WFLG_SIZEBRIGHT flag puts the sizing gadget in the right border. The WFLG_SIZEBBOTTOM flag puts the sizing gadget in the bottom border. Both flags may be specified, placing the gadget in both borders. Equivalent to NewWindow.Flags WFLG_SIZEGADGET.
WA_SizeBRight
Place the size gadget in the right border. Equivalent to NewWindow.Flags WFLG_SIZEBRIGHT.
WA_SizeBBottom
Place the size gadget in the bottom border. Equivalent to NewWindow.Flags WFLG_SIZEBBOTTOM.
WA_DragBar
This flag turns the entire title bar of the window into a drag gadget, allowing the user to position the window by clicking in the title bar and dragging the mouse. Equivalent to NewWindow.Flags WFLG_DRAGBAR.
WA_DepthGadget
Setting this flag adds a depth gadget to the window. This allows the user to change the window's depth arrangement with respect to other windows on the screen. Intuition places the depth gadget in the upper right corner of the window. Equivalent to NewWindow.Flags WFLG_DEPTHGADGET.
WA_CloseGadget
Setting this flag attaches a close gadget to the window. When the user selects this gadget, Intuition transmits a message to the application. It is up to the application to close the window with a CloseWindow() call. Intuition places the close gadget in the upper left corner of the window. Equivalent to NewWindow.Flags WFLG_CLOSEGADGET.
WA_ReportMouse
Send mouse movement events to the window as x,y coordinates. Also see the description of the IDCMP flag IDCMP_MOUSEMOVE, in Intuition Input and Output Methods. Equivalent to NewWindow.Flags WFLG_REPORTMOUSE.
The WFLG_REPORTMOUSE flag in the Flags field of the Window structure may be modified on the fly by the program. Changing this flag must be done as an atomic operation. Most compilers generate atomic code for operations such as window->flags |= WFLG_REPORTMOUSE or window->flags &= ~WFLG_REPORTMOUSE. If you are unsure of getting an atomic operation from your compiler, you may wish to do this operation in assembler, or bracket the code with a Forbid()/Permit() pair.
The use of the ReportMouse() function is strongly discouraged, due to historic confusion over the parameter ordering.
WA_NoCareRefresh
This window does not want IDCMP_REFRESHWINDOW events. Set this flag to prevent the window from receiving refresh window messages. Equivalent to NewWindow.Flags WFLG_NOCAREREFRESH. Intuition will manage BeginRefresh() and EndRefresh() internally.
WA_Borderless
Open a window with no borders rendered by Intuition. Equivalent to NewWindow.Flags WFLG_BORDERLESS.
Use caution setting this flag, as it may cause visual confusion on the screen. Also, some borders may be rendered if any of the system gadgets are requested, if text is supplied for the window's title bar, or if any of application gadgets are in the borders.
WA_Backdrop
Make this window a Backdrop window. Equivalent to NewWindow.Flags WFLG_BACKDROP.
WA_GimmeZeroZero
Set this tag to create a GimmeZeroZero window. GimmeZeroZero windows have the window border and border gadgets rendered into an extra layer. This extra layer slows down window operations, thus it is recommended that applications only use GimmeZeroZero windows when they are required. For clipping graphics to the area within the borders of a window, see the discussion of "Regions" in Layers Library. Equivalent to NewWindow.Flags WFLG_GIMMEZEROZERO.
WA_Activate
Activate the window when it opens. Equivalent to NewWindow.Flags WFLG_ACTIVATE. Use this flag carefully, as it can change where the user's input is going.
WA_RMBTrap
Catch right mouse button events for application use. Set this flag to disable menu operations for the window. When set, right mouse button events will be received as IDCMP_MOUSEBUTTONS with the MENUUP and MENUDOWN qualifiers. Equivalent to NewWindow.Flags WFLG_RMBTRAP.
The WFLG_RMBTRAP flag in the Window structure Flags field may be modified on the fly by the program. Changing this flag must be done as an atomic operation, as Intuition can preempt a multistep set or clear operation. An atomic operation can be done in assembler, using 68000 instructions that operate directly on memory. If you are unsure of generating such an instruction, place the operation within a Forbid()/Permit() pair. This will ensure proper operation by disabling multitasking while the flag is being changed.
WA_SimpleRefresh
The application program takes complete responsibility for updating the window. Only specify if TRUE. Equivalent to NewWindow.Flags WFLG_SIMPLE_REFRESH.
WA_SmartRefresh
Intuition handles all window updating, except for parts of the window revealed when the window is sized larger. Only specify if TRUE. Equivalent to NewWindow.Flags WFLG_SMART_REFRESH.
WA_SmartRefresh windows without a sizing gadget will never receive refresh events due to the user sizing the window. However, if the application sizes the window through a call like ChangeWindowBox(), ZipWindow() or SizeWindow(), a refresh event may be generated. Use WA_NoCareRefresh to disable refresh events.
WA_SuperBitMap
This is a pointer to a BitMap structure for a SuperBitMap window. The application will be allocating and maintaining its own bitmap. Equivalent to NewWindow.BitMap. Setting this tag implies the WFLG_SUPER_BITMAP property.
For complete information about SuperBitMap, see "Setting Up a SuperBitMap Window".
WA_AutoAdjust
Allow Intuition to change the window's position and dimensions in order to fit it on screen. The window's position is adjusted first, then the size. This property may be especially important when using WA_InnerWidth and WA_InnerHeight as border size depends on a user specified font.
WA_MenuHelp
Enables IDCMP_MENUHELP: pressing Help during menus will return IDCMP_MENUHELP message. See the Intuition Menus for more information.
WA_Flags
Multiple initialization of window flags, equivalent to NewWindow.Flags. Use the WFLG_ constants to initialize this field, multiple bits may be set by ORing the values together.
WA_BackFill
Allows you to specify a backfill hook for your window's layer. See the description of CreateUpFrontHookLayer() in Layers Library.

Opening a Window

A window is opened and displayed by a call to one of the OpenWindow() functions: OpenWindow(), OpenWindowTagList() or OpenWindowTags().

struct Window *OpenWindowTagList( struct NewWindow *newWindow, struct TagItem *tagList );
struct Window *OpenWindowTags( struct NewWindow *newWindow, ULONG tag1Type, ... );
struct Window *OpenWindow( struct NewWindow *newWindow );

The type of window and its attributes are specified in NewWindow or TagItem structures depending on which function is used. These functions all return a pointer to a new Window structure if they succeed. A NULL return indicates failure.

For the OpenWindowTagList() and OpenWindowTags() functions, window attributes are specified in TagItem structures which are paired data items specifying an attribute and its setting. (See Utility Library for more information on TagItems.)

OpenWindow() is available in all versions of the OS. Window attributes can be specified using a NewWindow structure but only a limited set of window attributes are available this way. To support both the new window features and compatibility with older versions of the OS, use OpenWindow() with an extended version of the NewWindow structure named ExtNewWindow. See the WFLG_NW_EXTENDED flag description in the "Window Attributes" section below for more information on using OpenWindow() with the extended NewWindow structure.

Further references to OpenWindow() in this chapter will apply to all three functions. These calls are the only proper method for allocating a Window structure. The tag based versions are recommended for V36 and later versions of the OS. Use the ExtNewWindow structure with OpenWindow() to provide backward compatibility.

OpenWindowTagList() Example

Here's an example showing how to open a new window using the OpenWindowTagList() function with window attributes set up in a TagItem array.

/*
** openwindowtags.c - open a window using tags.
*/
 
#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <intuition/screens.h>
 
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
 
#define MY_WIN_LEFT   (20)
#define MY_WIN_TOP    (10)
#define MY_WIN_WIDTH  (300)
#define MY_WIN_HEIGHT (110)
 
void handle_window_events(struct Window *);
 
struct IntuitionIFace *IIntuition = NULL;
 
struct TagItem win_tags[] =
    {
    {WA_Left,       MY_WIN_LEFT},
    {WA_Top,        MY_WIN_TOP},
    {WA_Width,      MY_WIN_WIDTH},
    {WA_Height,     MY_WIN_HEIGHT},
    {WA_CloseGadget,TRUE},
    {WA_IDCMP,      IDCMP_CLOSEWINDOW},
    {TAG_END, NULL},
    };
 
/*
** Open a simple window using OpenWindowTagList()
*/
int main(int argc, char **argv)
{
struct Window *win;
 
struct Library *IntuitionBase = IExec->OpenLibrary("intuition.library", 50);
IIntuition = (struct IntuitionIFace*)IExec->GetInterface(IntuitionBase, "main", 1, NULL);
 
if (IIntuitionBase != NULL)
    {
    win = IIntuition->OpenWindowTagList(NULL,win_tags);
    if (win==NULL)
        {
        /* window failed to open */
        }
    else
        {
        /* window successfully opened here */
        handle_window_events(win);
 
        IIntuition->CloseWindow(win);
        }
    }
 
IExec->DropInterface((struct Interface*)IIntuition);
IExec->CloseLibrary((struct Library *)IntuitionBase);
 
return 0;
}
 
/* Normally this routine would contain an event loop like the one given
** in the chapter "Intuition Input and Output Methods".  Here we just
** wait for any messages we requested to appear at the Window's port.
*/
VOID handle_window_events(struct Window *win)
{
IExec->WaitPort(win->UserPort);
}

Setting Window Attributes

Depending on which function is used to open a window, the window's attributes may be specified using TagItems, or a NewWindow structure or an ExtNewWindow structure. In the code above, the window attributes are set up with an array of TagItems:

struct TagItem win_tags[] =
    {
    {WA_Left,       MY_WIN_LEFT},
    {WA_Top,        MY_WIN_TOP},
    {WA_Width,      MY_WIN_WIDTH},
    {WA_Height,     MY_WIN_HEIGHT},
    {WA_CloseGadget,TRUE},
    {WA_IDCMP,      IDCMP_CLOSEWINDOW},
    {TAG_END,       NULL},
    };

These window attributes set the window's position (WA_Left, WA_Top) and size (WA_Width, WA_Height), request a close gadget on the window (WA_CloseGadget) and ask Intuition to send a message whenever the user activates the close gadget (WA_IDCMP).

Throughout this chapter window attributes are referred to by their TagItem ID name (the name is always prefixed with "WA_"). See the section below on "Window Attributes" for a complete list.

Closing Windows

Call the CloseWindow() function to close a window, remove its imagery from the display, and clean up any system resources used by the window. Typically, you call CloseWindow() when Intuition informs you that the user has selected the window's close gadget but this is not a requirement nor does the window have to be active to be closed.

VOID CloseWindow( struct Window *window );

Pass this function a pointer to the Window structure returned by one of the OpenWindow() calls.

If you call CloseWindow() on the active window, the previously active window (if available) will become the active window. If the previously active window has already closed, then the window active prior to that window will become the active window. (Applications should not rely on this behavior. To make a specific window become active, call the ActivateWindow() function.)

Intuition does not automatically close a window when the user selects the close window gadget. Instead, Intuition sends your program a message about the user's action. The program can then perform whatever cleanup is necessary before closing the window with the CloseWindow() function.

Windows and Screens

Windows may be opened on one of three screen types: a custom screen, a public screen or the Workbench screen. A custom screen is one created and controlled by your application. Once you have set up a custom screen, you may open a window on it directly by calling one of the three open window functions.

To open a window on a custom screen, call OpenWindowTagList() (or OpenWindowTags()) with the WA_CustomScreen tag along with a pointer to the custom screen. This must be a pointer to a screen created by your application.

You may choose to open a window on an existing public (shareable) screen instead of setting up your own custom screen. Such windows are often referred to as visitor windows because they "visit" a screen managed by the system or another application.

For Workbench or other public screens that are not created and managed directly by your application, you must lock the screen before opening the window. This ensures that the screen remains open while your call to open the window is processed. One way to obtain a lock on a public screen is by calling the LockPubScreen() function (see Intuition Screens).

Use WA_PubScreenName with NULL to open a visitor window on the default public screen (normally the Workbench screen). If a name is provided and the named screen exists, the visitor window will open on that named screen. In this case the system locks the named screen for you so there is no need to call LockPubScreen() directly. The open window call will fail if it cannot obtain a lock on the screen. If the WA_PubScreenFallBack tag is TRUE, the window will open on the default public screen when WA_PubScreenName can't be found.

Another method to open a visitor window on a public screen is to use the WA_PubScreen tag along with a pointer to the Screen structure of the public screen obtained via LockPubScreen().

The application may also request the name of the "next" public screen, which allows windows to "jump" between public screens. This is done by closing the application window on the first screen and opening a new window on the next screen. (See Intuition Screens for more information on public and custom screens.)

If no action is taken by the programmer to open the window on a specific screen, the window will open on the default public screen (normally the Workbench). This behavior is shown in the above example using OpenWindowTagList().

There are two global modes which come into play when a visitor window is opened on a public screen. If the global mode SHANGHAI is set, Workbench application windows will be opened on the default public screen. A second global mode, POPPUBSCREEN, forces a public screen to be moved to the font when a visitor window opens on it. These modes can be changed using SetPubScreenModes(), however, these should only be set according to the preferences of the user.

Simple Window on a Public Screen Example

/*
** winpubscreen.c
** open a window on the default public screen (usually the Workbench screen)
*/
 
#include <exec/types.h>
#include <intuition/intuition.h>
 
#include <proto/exec.h>
#include <proto/intuition.h>
 
struct IntuitionIFace *IIntuition;
 
/* our function prototypes */
VOID handle_window_events(struct Window *win);
 
 
/*
** Open a simple window on the default public screen,
** then leave it open until the user selects the close gadget.
*/
int main(int argc, char **argv)
{
  struct Window *test_window = NULL;
  struct Screen *test_screen = NULL;
 
  struct Library *IntuitionBase = IExec->OpenLibrary("intuition.library", 50);
  IIntuition = (struct IntuitionIFace*)IExec->GetInterface(IntuitionBase, "main", 1, NULL);
 
  if (IIntuitionBase != NULL)
  {
    /* get a lock on the default public screen */
    if (test_screen = IIntuition->LockPubScreen(NULL))
    {
      /* open the window on the public screen */
      test_window = IIntuition->OpenWindowTags(NULL,
                    WA_Left,  10,    WA_Top,    20,
                    WA_Width, 300,   WA_Height, 100,
                    WA_DragBar,         TRUE,
                    WA_CloseGadget,     TRUE,
                    WA_SmartRefresh,    TRUE,
                    WA_NoCareRefresh,   TRUE,
                    WA_IDCMP,           IDCMP_CLOSEWINDOW,
                    WA_Title,           "Window Title",
                    WA_PubScreen,       test_screen,
                    TAG_END);
 
      /* Unlock the screen.  The window now acts as a lock on
      ** the screen, and we do not need the screen after the
      ** window has been closed.
      */
      IIntuition->UnlockPubScreen(NULL, test_screen);
 
      /* if we have a valid window open, run the rest of the
      ** program, then clean up when done.
      */
      if (test_window)
      {
        handle_window_events(test_window);
        IIntuition->CloseWindow(test_window);
      }
    }
  }
 
  IExec->DropInterface((struct Interface*)IIntuition);
  IExec->CloseLibrary(IntuitionBase);
 
  return 0;
}
 
/*
** Wait for the user to select the close gadget.
*/
VOID handle_window_events(struct Window *win)
{
  struct IntuiMessage *msg;
  BOOL done = FALSE;
 
  while (! done)
    {
    /* We have no other ports of signals to wait on,
    ** so we'll just use WaitPort() instead of Wait()
    */
    IExec->WaitPort(win->UserPort);
 
    while ( (! done) &&
            (msg = (struct IntuiMessage *)IExec->GetMsg(win->UserPort)))
        {
        /* use a switch statement if looking for multiple event types */
        if (msg->Class == IDCMP_CLOSEWINDOW)
            done = TRUE;
 
        IExec->ReplyMsg((struct Message *)msg);
        }
    }
}

Windows and Menus

Menus for the active window will be displayed when the user presses the menu button on the mouse. Menus may be disabled for the window by not providing a menu strip, or by clearing the menus with ClearMenuStrip(). Similarly, if the active window has WFLG_RMBTRAP set, the menu button will not bring up the menus.

Two other functions, SetMenuStrip() and ResetMenuStrip(), are used to attach or update the menu strip for a window.

VOID ClearMenuStrip( struct Window *window );
BOOL SetMenuStrip( struct Window *window, struct Menu *menu );
BOOL ResetMenuStrip( struct Window *window, struct Menu *menu );

If SetMenuStrip() has been called for a window, ClearMenuStrip() must be called before closing the window. After ClearMenuStrip() has been called, the user can no longer access menus for this window. See Intuition Menus, for complete information about setting up menus.

Graphics and Text in Windows

Applications can call functions in both the graphics library and the Intuition library to render images, lines, text and other graphic elements in windows. The graphics library provides primitive operations such as area fill, line drawing, text and animation.

The number of colors and the palette available in a window are defined by the screen in which the window opens. Applications should never change the palette of a screen unless the screen is a custom screen created by the application.

Graphics rendered into the window should respect the drawing pens defined for the screen. See the section on "DrawInfo and the 3D Look" in Intuition Screens for more information.

Default window fonts come from one of two places, depending on the screen on which the window opens. The window title font is always taken from the screen font. If the screen is opened with a font specified, either by specifying the tag SA_Font or the variable NewScreen.Font, then Window.RPort->Font is taken from the screen's font. Otherwise, the window's rastport's font is taken from GfxBase->DefaultFont. This information is available to the application if it opened the screen.

If the application did not open the screen, it has no way of knowing which font has been used for the window. Applications that require to know the window's font before the window is open must explicitly set the font (using SetFont()) for that window after opening it. In this case, the application may use any font it desires. It is recommended that applications use the screen's font if they support proportional fonts, and GfxBase->DefaultFont otherwise, as these fonts are generally the user's preference.

Intuition also provides a minimal high level interface to some of the functions in the Graphics library. This includes calls to draw lines, text and images. See Intuition Images, Line Drawing and Text for more information about using Intuition to render graphics.

Window Dimensions

The initial position and dimensions of the window are defined in the OpenWindowTagList() call. These values undergo error checking before the window is actually opened on the screen. If the dimensions are too big, the window will fail to open. (Or, you can use the WA_AutoAdjust tag if you want Intuition to move or size your window to fit.)

Maximum and minimum size values may also be defined, but are not required If the window does not have a sizing gadget. In setting these dimensions, bear in mind the horizontal and vertical resolutions of the screen in which the window will open.

The maximum dimensions of the window are unsigned values and may legally be set to the maximum by using the value 0xFFFF, better expressed as "~0". Using this value for the maximum dimensions allows the window to be sized to the full screen.

A Display Sized Window Example

A full screen window is not always desirable. If the user is working on a large, scrolling screen, they may only want a window the size of the visible display. The following example calculates the visible area on a screen and opens a window in that area. The example assumes that the screen display clip is as large or larger than text overscan (OSCAN_TEXT) which is set by the user. The window is opened in the text overscan area, not within the actual display clip that is used for the screen. Use QueryOverscan() to find the standard overscan rectangles (display clips) for a screen. Use the graphics library call VideoControl() to find the true display clip of the screen (see Graphics Primitives for more information on VideoControl()). The ViewPortExtra structure contains the display clip information.

About Screen Coordinates
The screen's actual position may not exactly equal the coordinates given in the LeftEdge and TopEdge fields of the Screen structure. This is due to hardware constraints that limit the fineness of the positioning of the underlying constructs. This may cause a window which is opened in the visible part of the screen to be incorrectly positioned by a small number of pixels in each direction. See the discussion of the screen's LeftEdge and TopEdge in Intuition Screens for more information.
/* visiblewindow.c
**
** open a window on the visible part of a screen, with the window as large
** as the visible part of the screen.  It is assumed that the visible part
** of the screen is OSCAN_TEXT, which how the user has set their preferences.
*/
#define INTUI_V36_NAMES_ONLY
 
#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <graphics/displayinfo.h>
 
#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
 
/* Minimum window width and height:
** These values should really be calculated dynamically given the size
** of the font and the window borders.  Here, to keep the example simple
** they are hard-coded values.
*/
#define MIN_WINDOW_WIDTH  (100)
#define MIN_WINDOW_HEIGHT (50)
 
/* minimum and maximum calculations...Note that each argument is
** evaluated twice (don't use max(a++,foo(c))).
*/
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<=(b)?(a):(b))
 
struct IntuitionIFace *IIntuition;
struct GraphicsIFace *IGraphics;
 
/* our function prototypes */
VOID handle_window_events(struct Window *win);
VOID fullScreen(VOID);
 
/*
** open all the libraries and run the code.  Cleanup when done.
*/
int main()
{
    struct Library *GfxBase = IExec->OpenLibrary("graphics.library", 50);
    IGraphics = (struct GraphicsIFace*)IExec->GetInterface(GfxBase, "main", 1, NULL);
 
    struct Library *IntuitionBase = IExec->OpenLibrary("intuition.library", 50);
    IIntuition = (struct IntuitionIFace*)IExec->GetInterface(IntuitionBase, "main", 1, NULL);
 
    if (IGraphics != NULL && IIntuition != NULL)
    {
        fullScreen();
    }
 
    IExec->DropInterface((struct Interface*)IIntuition);
    IExec->CloseLibrary(IntuitionBase);
 
    IExec->DropInterface((struct Interface*)IGraphics);
    IExec->CloseLibrary(GfxBase);
 
    return 0;
}
 
 
/*
** Open a window on the default public screen, then leave it open until the
** user selects the close gadget. The window is full-sized, positioned in the
** currently visible OSCAN_TEXT area.
*/
VOID fullScreen(VOID)
{
    struct Screen *pub_screen;
 
    int32 left  = 0;   /* set some reasonable defaults for left, top, width and height. */
    int32 top   = 0;   /* we'll pick up the real values with the call to QueryOverscan(). */
    int32 width = 640;
    int32 height= 200;
 
    /* get a lock on the default public screen */
    if (NULL != (pub_screen = IIntuition->LockPubScreen(NULL)))
    {
        /* this technique returns the text overscan rectangle of the screen that we
        ** are opening on.  If you really need the actual value set into the display
        ** clip of the screen, use the VideoControl() command of the graphics library
        ** to return a copy of the ViewPortExtra structure.  See the Graphics
        ** library chapter and Autodocs for more details.
        */
 
        uint32 screen_modeID = IGraphics->GetVPModeID(&pub_screen->ViewPort);
        if(screen_modeID != INVALID_ID)
        {
            struct Rectangle rect;
            if (IGraphics->QueryOverscan(screen_modeID, &rect, OSCAN_TEXT))
            {
                /* make sure window coordinates are positive or zero */
                left = max(0, -pub_screen->LeftEdge);
                top  = max(0, -pub_screen->TopEdge);
 
                /* get width and height from size of display clip */
                width  = rect.MaxX - rect.MinX + 1;
                height = rect.MaxY - rect.MinY + 1;
 
                /* adjust height for pulled-down screen (only show visible part) */
                if (pub_screen->TopEdge > 0)
                    height -= pub_screen->TopEdge;
 
                /* insure that window fits on screen */
                height = min(height, pub_screen->Height);
                width  = min(width,  pub_screen->Width);
 
                /* make sure window is at least minimum size */
                width  = max(width,  MIN_WINDOW_WIDTH);
                height = max(height, MIN_WINDOW_HEIGHT);
            }
        }
 
        /* open the window on the public screen */
        struct Window *test_window = IIntuition->OpenWindowTags(NULL,
            WA_Left,        left,
            WA_Width,       width,
            WA_Top,         top,
            WA_Height,      height,
            WA_CloseGadget, TRUE,
            WA_IDCMP,       IDCMP_CLOSEWINDOW,
            WA_PubScreen,   pub_screen,
            TAG_END);
 
        /* unlock the screen.  The window now acts as a lock on the screen,
        ** and we do not need the screen after the window has been closed.
        */
        IIntuition->UnlockPubScreen(NULL, pub_screen);
 
        /* if we have a valid window open, run the rest of the
        ** program, then clean up when done.
        */
        if (test_window)
        {
            handle_window_events(test_window);
            IIntuition->CloseWindow(test_window);
        }
    }
}
 
 
/*
** Wait for the user to select the close gadget.
*/
VOID handle_window_events(struct Window *win)
{
    struct IntuiMessage *msg;
    BOOL done = FALSE;
 
    while (! done)
    {
        /* we only have one signal bit, so we do not have to check which
        ** bit(s) broke the Wait() (i.e. the return value of Wait)
        */
        IExec->Wait(1L << win->UserPort->mp_SigBit);
 
        while ( (! done) &&
                (msg = (struct IntuiMessage *)IExec->GetMsg(win->UserPort)))
        {
            /* use a switch statement if looking for multiple event types */
            if (msg->Class == IDCMP_CLOSEWINDOW)
                done = TRUE;
 
            IExec->ReplyMsg((struct Message *)msg);
        }
    }
}

Window Border Dimensions

Intuition automatically draws a border around a window unless directed otherwise, such as by setting the WFLG_BORDERLESS flag. Borderless windows may not have a window title or gadgets in the border (this includes the standard system gadgets). Otherwise they won't come out properly borderless.

The size of the border of an open window is available in the Window structure variables BorderLeft, BorderTop, BorderRight and BorderBottom. Intuition fills these in when the window is opened. To calculate the window border sizes before the window is opened you use information in the Screen structure as shown in the next listing.

Gadgets Can Change Border Sizes
The following calculations do not take application border gadgets into account. If the program adds gadgets into the window's borders, Intuition will expand the borders to hold the gadgets.
if (NULL != (screen = IIntuition->LockPubScreen(NULL)))
    {
    top_border    = screen->WBorTop + screen->Font->ta_YSize + 1;
    left_border   = screen->WBorLeft;
    right_border  = screen->WBorRight;
    bottom_border = screen->WBorBottom;
 
    IIntuition->UnlockPubScreen(NULL,screen);
    }
 
/* if the sizing gadget is specified, then the border size must
** be adjusted for the border containing the gadget.  This may
** be the right border, the bottom border or both.
**
** We are using fixed values.  There is currently no system-approved
** method of finding this information before the window is opened.
** If you need to know these sizes BEFORE your window is opened,
** use the fixed values below.  Otherwise, use Window->BorderRight,
** etc. AFTER you have opened your window.
*/
 
/* values for non-lo-res screen */
right_border  = 18;  /* if sizing gadget in right border  */
bottom_border = 10;  /* if sizing gadget in bottom border */
 
/* values for lo-res screen */
right_border  = 13;  /* if sizing gadget in right border  */
bottom_border = 11;  /* if sizing gadget in bottom border */

Use the border sizes to position visual elements within the window. Coordinates may be offset into the window by the size of the top and left borders, for instance (x, y) becomes (x + BorderLeft, y + BorderTop). This may look clumsy, but it offers a way of avoiding a GimmeZeroZero window, which, although much more convenient to use, requires extra memory and degrades performance.

The right and bottom border values specify the width of these borders. The area within the borders of a window is defined as (BorderLeft, BorderTop) to (Width - 1 - BorderRight, Height - 1 - BorderBottom). The calculations subtract one from the height and width of the windows as positions count from zero, but dimensions count from one.

The window title bar is only available if one or more of the following is specified: window title, window drag gadget, window depth gadget, window close gadget or window zoom gadget. If none of these are specified, the top border will be much narrower.

Application gadgets may be added to the window border by setting a flag in the Gadget structure. A special flag must additionally be set to place gadgets into the borders of GimmeZeroZero windows. See Intuition Gadgets for more information about gadgets and their positioning. (Borderless windows have no visible border outlines and gadgets should not be placed in their borders.)

Changing Window Size Limits

To change the sizing limits after the window has been opened, call WindowLimits() with the new values.

BOOL WindowLimits( struct Window *window, LONG widthMin, LONG heightMin,
                   ULONG widthMax, ULONG heightMax );

To maintain the current dimension, set the corresponding argument to 0. Out of range numbers are ignored. If the user is currently sizing the window, new limits take effect after the user releases the select button.

Changing the Window or Screen Title

Each window has its own window title and local screen title. The window title, if specified, is always displayed in the window. The local screen title, if specified, is only displayed in the screen's title bar when the window is active. If the window does not specify a local screen title, then the default screen title is used in the screen title bar when this window is active.

VOID SetWindowTitles( struct Window *window, STRPTR windowTitle,
                      STRPTR screenTitle );

This function changes the window title or local screen title for the given window. Both windowTitle and screenTitle can be set to -1, NULL or a NULL terminated string. Specifying -1 will not change the title from the current value. Specifying NULL will clear the window title or reset the screen title to the default title for the screen.

Changing Message Queue Limits

Windows have limits on the number of mouse movement and repeat key messages that may be waiting at their IDCMP at any time. These queue limits prevent the accumulation of these messages, which may arrive at the IDCMP message port in large numbers.

Once a queue limit is reached, further messages of that type will be discarded by Intuition. The application will never hear about the discarded messages; they are gone forever. (Note that only mouse move and key repeat messages are limited this way. Other types of messages will still be added to the port.) Messages of the limited type will arrive at the port again after the application has replied to one of the messages in the queue.

The queue limits are independent of each other. Having reached the limit for one type of message does not prevent other types of messages (that have not yet reached their queuing limits) from being added to the IDCMP. Note that the queues apply only to the IDCMP and not to messages received directly via an input handler or from the console device.

Order of event arrival is not a factor in the message count. Messages may be sequential or interspersed with other events-only the number of messages of the specific type waiting at the IDCMP matters.

The WA_RptQueue tag allows setting an initial value for the repeat key backlog limit for the window. There is no function to change this value. The default value for WA_RptQueue is 3.

The WA_MouseQueue tag allows setting an initial value for the mouse message backlog limit for the window. The default value for WA_MouseQueue is 5. The number may later be changed with a call to SetMouseQueue():

LONG SetMouseQueue( struct Window *window, ULONG queueLength );

Note that real information may be lost if the queue fills and Intuition is forced to discard messages. See Intuition Mouse for more information.

Changing Pointer Position Reports

Pointer position messages to a window may be turned on and off by simply setting or clearing the WFLG_REPORTMOUSE flag bit in Window->Flags, in an atomic way, as explained for the WA_RMBTrap tag in the "Window Attributes" section above. Using this direct method of setting the flag avoids the historic confusion on the ordering of the arguments of the ReportMouse() function call.

Mouse reporting may be turned on even if mouse movements were not activated when the window was opened. The proper IDCMP flags must be set for the window to receive the messages. See Intuition Mouse for more details on enabling mouse reporting in an application.

Custom Pointers

The active window also has control over the pointer. If the active window changes the image for the pointer using the functions SetPointer() or ClearPointer(), the pointer image will change:

VOID SetPointer( struct Window *window, UWORD *pointer, LONG height,
                 LONG width, LONG xOffset, LONG yOffset );
 
VOID ClearPointer( struct Window *window );

SetPointer() sets up the window with a sprite definition for a custom pointer. If the window is active, the change takes place immediately. The pointer will not change if an inactive window calls SetPointer(). In this way, each window may have its own custom pointer that is displayed only when the window is active.

ClearPointer() clears the custom pointer from the window and restores it to the default Intuition pointer, which is set by the user. Setting a pointer for a window is discussed further in Intuition Pointer.

Program Control of Window Arrangement

MoveWindow(), SizeWindow(), WindowToFront() and WindowToBack() allow the program to modify the size and placement of its windows. These calls are available in all versions of the operating system.

MoveWindowInFrontOf(), ChangeWindowBox() and ZipWindow() provide more flexible control over the size and placement of windows.

All of these functions are asynchronous. The window will not be affected by them immediately, rather, Intuition will act on the request the next time it receives an input event. Currently this happens at a minimum rate of ten times per second, and a maximum of sixty times per second. There is no guarantee that the operation has taken place when the function returns. In some cases, there are IDCMP messages which will inform the application when the change has completed (for example, an IDCMP_NEWSIZE event indicates that a resize operation has completed).

Use the MoveWindow() function to move a window to a new position in the screen. Use SizeWindow() to change the size of the window:

VOID MoveWindow( struct Window *window, LONG dx, LONG dy );
VOID SizeWindow( struct Window *window, LONG dx, LONG dy );

Note that both MoveWindow() and SizeWIndow() take the amount of change in each axis (delta values instead of absolute coordinates). To specify the coordinates as absolute numbers, use ChangeWindowBox(). The SizeWindow() function will respect the window's maximum and minimum dimensions only if the window has a sizing gadget.

ChangeWindowBox() allows an application to change the window size and position in a single call:

VOID ChangeWindowBox( struct Window *window, LONG left, LONG top, LONG width, LONG height );

Note that the position and size values are absolutes and not deltas. The window's maximum and minimum dimensions are always respected.

To depth arrange windows under program control, use WindowToFront() and WindowToBack():

VOID WindowToFront( struct Window *window );
VOID WindowToBack( struct Window *window );

WindowToFront() depth arranges a given window in front of all other windows on its screen. WindowToBack() depth arranges a given window behind all other windows on its screen.

To move a window in front of a specific, given window (as opposed to all windows), use MoveWindowInFrontOf():

VOID MoveWindowInFrontOf( struct Window *window, struct Window *behindWindow );

To toggle the window size between its two zoom settings use ZipWindow(). This performs the same action that occurs when the user selects the zoom gadget:

VOID ZipWindow( struct Window *window );

The two zoom settings are the initial size and position of the window when it was first opened and the alternate position specified with the WA_Zoom tag. If no WA_Zoom tag is provided, the alternate position is taken from the window's minimum dimensions, unless the window was opened at its minimum dimension. In that case, the alternate position is taken from the window's maximum dimension.