Copyright (c) Hyperion Entertainment and contributors.

Intuition Pointer

From AmigaOS Documentation Wiki
Jump to navigation Jump to search

The Pointer

The system provides a pointer to allow the user to make selections from menus, choose gadgets, and so on. The user may control the pointer with a mouse, the keyboard cursor keys or some other type of controller. The specific type of controller is not important, as long as the proper types of input events can be generated.

The pointer is associated with the active window and the input focus. The active window controls the pointer imagery and receives the input stream from the mouse. The pointer and mouse may be used to change the input focus by selecting another window.

Pointer Position

There are two ways to determine the position of the pointer: by direct examination of variables in the window structure at any time, and by examining messages sent by Intuition which inform the application of pointer movement. The pointer coordinates are relative to the upper left corner of the window and are reported in the resolution of the screen, even though the pointer's visible resolution is always in low-resolution pixels (note that the pointer is actually a sprite).

The MouseX and MouseY fields of the Window structure always contain the current pointer x and y coordinates, whether or not the window is the active one. If the window is a GimmeZeroZero window, the variables GZZMouseX and GZZMouseY in the Window structure contain the position of the mouse relative to the upper left corner of the inner window.

If the window is receiving mouse move messages, it will get a set of x,y coordinates each time the pointer moves. To receive messages about pointer movements, the WFLG_REPORTMOUSE flag must be set in the Window structure. This flag can be set when the window is opened. The flag can also be modified after the window is open by calling ReportMouse(), however C programmers should avoid this function. ReportMouse() has problems due to historic confusion about the ordering of its C language arguments. Do not use ReportMouse() unless you are programming in assembler. C programmers should set the flag directly in the Window structure using an atomic operation.

Most compilers generate atomic code for operations such as mywindow->flags |= WFLG_REPORTMOUSE or mywindow->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.

After the WFLG_REPORTMOUSE flag is set, whenever the window is active it will be sent an IDCMP_MOUSEMOVE messages each time the pointer position changes. The window must have the IDCMP flag IDCMP_MOUSEMOVE set to receive these messages.

Mouse movements can cause a very large number of messages to be sent to the IDCMP, the application should be prepared to handle them efficiently.

Messages about pointer movements may also be activated by setting the flag GACT_FOLLOWMOUSE in an application gadget structure. When this flag is set in a gadget, changes in the pointer position are reported as long as the gadget is selected by the user. These messages are also sent as IDCMP_MOUSEMOVE messages.

Custom Pointer

An application can set a custom pointer for a window to replace the default pointer. This custom pointer will be displayed whenever the window is the active one.

To place a custom pointer in a window, call SetPointer().

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

Set the window argument to the address of the window that is to receive this custom pointer definition. The pointer argument is the address of the data that defines the custom pointer image. The format of this data is discussed in the next section, "The Sprite Data Structure".

The height and width specify the dimensions of the pointer sprite. There is no height restriction but the width of the sprite must be less than or equal to 16.

The xOffset and yOffset are used to offset the top left corner of the hardware sprite imagery from what Intuition regards as the current position of the pointer. Another way of describing this is the offset of the default Intuition pointer hot spot from the top left corner of the sprite.

For instance, by specifying offsets of (0,0), the top left corner of the sprite image will be placed at the pointer position. On the other hand, specifying an xOffset of -7 (remember, sprites are 16 pixels wide) will center the sprite over the pointer position. Specifying an xOffset of -15 will place the right edge of the sprite will be over the pointer position.

Specifying the Hot Spot
For compatibility, the application must specify that the "hot spot" of the pointer is one pixel to the left of the desired position. Changes to the pointer done by a program must compensate for this. The Preferences Pointer editor correctly handles this situation.
VOID ClearPointer( struct Window *window );

Set the window argument to the address of the window that is to have its custom pointer definition cleared. The pointer will be restored to the default Intuition pointer imagery

SetPointer() and ClearPointer() take effect immediately if the window is active, otherwise, the change will only be displayed when the window is made active.

The Sprite Data Structure

To define the pointer, set up a sprite data structure (sprites are one of the general purpose Amiga graphics structures). The sprite image data must be located in Chip memory, which is memory that can be accessed by the special Amiga hardware chips. Expansion, or Fast memory cannot be addressed by the custom chips. Ensure that data is in Chip memory by using the AllocMem() function with the MEMF_CHIP flag, and copying the data to the allocated space. Alternately, use the tools or flags provided by each compiler for this purpose. See Exec Memory Allocation for more information.

A sprite data structure is made up of words of data. In a pointer sprite, the first two words and the last two words are reserved for the system and should be set to zero. All other words contain the sprite image data.

The pointer in the example, a standard busy pointer, is sixteen lines high and sixteen pixels wide. Currently, all sprites are two bit planes deep, with one word of data for each line of each plane. The example sprite image consists of 36 words (2 planes * 18 lines = 36 words). Add to this the four reserved words of control information for a total of 40 words of data. See the example below for the complete data definition.

The sprite data words are combined to determine which color will appear at each pixel position of each row of the sprite. The first two words of image data, 0x0400 and 0x07C0, represent the top line of the sprite. The numbers must be viewed as binary numbers and combined in a bit-wise fashion. The highest bit from each word are combined to form a two bit number representing the color register for the leftmost pixel. The next two bits represent the next pixel in the row, and so on, until the low order bits from each word represent the rightmost pixel in the row.

For example:

LibFig10-1.png

Pointer Color Ordering. The first word in a line gives the least significant bit of the color register and the second word gives the most significant bit.

Sprites get their color information from the color registers much like screens do. See the Amiga Hardware Reference Manual for more information on the assignment of color registers to sprites. Note that the color number given above is added to a base number to determine the actual hardware color register.

The colors of the Intuition pointer may be changed. The Intuition pointer is always sprite 0. To change the colors of sprite 0, call the graphics library routine SetRGB4().

Pointer Example

The program below shows how to set the pointer for a window. In this example, the pointer imagery is changed to a stopwatch symbol which could be used to indicate a busy period.

;/* custompointer.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -y -j73 custompointer.c
Blink FROM LIB:c.o,custompointer.o TO custompointer LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit

** custompointer.c - Show the use of a custom busy pointer, as well as
** using a requester to block input to a window.
*/
#define INTUI_V36_NAMES_ONLY

#include <exec/types.h>
#include <exec/libraries.h>
#include <intuition/intuition.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/intuition_protos.h>

#ifdef LATTICE
int CXBRK(void)    { return(0); }  /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); }  /* really */
#endif

struct Library *IntuitionBase;


UWORD __chip waitPointer[] =
    {
    0x0000, 0x0000,     /* reserved, must be NULL */

    0x0400, 0x07C0,
    0x0000, 0x07C0,
    0x0100, 0x0380,
    0x0000, 0x07E0,
    0x07C0, 0x1FF8,
    0x1FF0, 0x3FEC,
    0x3FF8, 0x7FDE,
    0x3FF8, 0x7FBE,
    0x7FFC, 0xFF7F,
    0x7EFC, 0xFFFF,
    0x7FFC, 0xFFFF,
    0x3FF8, 0x7FFE,
    0x3FF8, 0x7FFE,
    0x1FF0, 0x3FFC,
    0x07C0, 0x1FF8,
    0x0000, 0x07E0,

    0x0000, 0x0000,     /* reserved, must be NULL */
    };


/*
** The main() routine
*/
VOID main(int argc, char **argv)
{
struct Window *win;
struct Requester null_request;
extern UWORD __chip waitPointer[];

if (IntuitionBase = OpenLibrary("intuition.library",37))
    {
    /* the window is opened as active (WA_Activate) so that the busy
    ** pointer will be visible.  If the window was not active, the
    ** user would have to activate it to see the change in the pointer.
    */
    if (win = OpenWindowTags(NULL,
                             WA_Activate, TRUE,
                             TAG_END))
        {
        /* a NULL requester can be used to block input
        ** in a window without any imagery provided.
        */
        InitRequester(&null_request);

        Delay(50);  /* simulate activity in the program. */

        /* Put up the requester to block user input in the window,
        ** and set the pointer to the busy pointer.
        */
        if (Request(&null_request, win))
            {
            SetPointer(win, waitPointer, 16, 16, -6, 0);

            Delay(100);  /* simulate activity in the program. */

            /* clear the pointer (which resets the window to the default
            ** pointer) and remove the requester.
            */
            ClearPointer(win);
            EndRequest(&null_request, win);
            }

        Delay(100);  /* simulate activity in the program. */

        CloseWindow(win);
        }
    CloseLibrary(IntuitionBase);
    }
}

Function Reference

The following are brief descriptions of the Intuition functions that relate to the use of the pointer under Intuition. See the SDK for details on each function call.

Function Description
SetPointer() Change the Intuition pointer imagery for an open window.
ClearPointer() Restore the default Intuition pointer imagery.