[ Next Article | Previous Article | Book Contents | Library Home | Legal | Search ]
GL3.2 Version 4.1 for AIX: Programming Concepts

Controlling Queues and Devices

This section discusses the following areas:

GL supports three classes of input devices:

valuators Return an integer value. For example, a dial on a dial and button box is a valuator. A mouse is a pair of valuators: one reports horizontal position and the other reports vertical position.
buttons Return a Boolean value: FALSE when they are not pressed (open) and TRUE when they are pressed (closed). Examples of buttons are keys on an unencoded keyboard, buttons on a mouse, and the switches on a dial and button box.
other devices Return information about other system events. For example, the keyboard returns ASCII characters. Most of these special devices register events. The keyboard device reports character values when keys (or combinations of keys) are pressed. If you press the A key, an ASCII a is reported; if you press the Shift key, nothing is reported. If you hold down the Shift key and then press the A key, an ASCII A is reported.

List of GL Queue and Device Control Subroutines

blkqread
                          Reads multiple entries from the event queue.
getbutton
                          Returns the current state of a button.
getdev
                          Reads a list of valuators.
getvaluator
                          Returns the current state of a valuator.
isqueued
                          Indicates whether a specified device is enabled for event queuing.
noise
                          Filters valuator motion.
qdevice
                          Enables an input device for event queuing.
qenter
                          Creates an event queue entry.
qread
                          Reads the first entry in the event queue.
qreset
                          Empties the event queue.
qtest
                          Checks the contents of the event queue.
setvaluator
                          Assigns an initial value to a valuator.
tie
                          Ties two valuators to a button.
unqdevice
                          Disables an input device for event queuing.

Understanding Windows and Input Control in GL introduces window and input control categories.

Polling and Queuing

Most input devices have an associated current value. If the input device is a button, the value is either 1 (pressed) or 0 (not pressed). If the device is a valuator, such as a dial or the x position of the mouse, its value is an integer that indicates the position of the device. Some special devices do not have an associated current value.

A program can get the value from input devices by either polling or queuing:

Input Queue versus Polling

In most cases, using the input queue is better than polling. For example, if you press and release a mouse button in an instant, a program that uses polling can miss the event (that the button was down) if it happened between two calls to getbutton(LEFTMOUSE).

For example, in a drawing program where you may want to indicate a series of vertices quickly and the system's calculations cannot keep up, queuing saves all the state changes so nothing is missed. This is so even if the program is doing something else when the event happens.

Devices that are queued act as asynchronous devices, independent of the user process. Whenever a device that is queued changes state, an entry is made in the event queue. If a program reads the queue in a timely fashion, no events are lost.

You can decide which devices, if any, to queue and establish some rules about what constitutes a state change, or event, for those devices. By default, no devices are queued.

Another difference between polling and queuing is that as long as a polled I/O device is active, it continues to send its value to the program that polls it. For instance, a call to getbutton(LEFTMOUSE) continues returning a value as long as you hold down the mouse button. In contrast, if the left mouse button had been queued, you could hold it down for any length of time and only one event is added to the queue. A second event is added to the queue only when the button is released and pressed a second time.

In addition to input subroutines, other subroutines control the characteristics of the peripheral input/output devices (see "Using the Keyboard"). These subroutines turn the keyboard click and the keyboard lights on and off; ring the keyboard bell; and control the lights on the dial and button box.

Device Descriptions

See the Input Buttons, Input Valuators, and Special Devices tables for listings of specific devices and their descriptions. Special devices, such as window manager, cursor, and ghost devices, are discussed in "Special Devices".

Input Buttons
Devices Description
MOUSE1 Right mouse button
MOUSE2 Middle mouse button
MOUSE3 Left mouse button
RIGHTMOUSE Right mouse button
MIDDLEMOUSE Middle mouse button
LEFTMOUSE Left mouse button
SW0...SW31 32 buttons on dial and button box
AKEY...PADENTER, BKEY...PADENTER All the keys on the keyboard
BPAD0 Pen stylus or button for digitizer tablet
BPAD1 Button for digitizer tablet
BPAD2 Button for digitizer tablet
BPAD3 Button for digitizer tablet
MENUBUTTON Menu button
Input Valuators
Devices Description
MOUSEX x valuator on mouse
MOUSEY y valuator on mouse
DIAL0...DIAL7 Dials on dial and button box
BPADX x valuator on digitizer tablet
BPADY y valuator on digitizer tablet
CURSORX x valuator attached to cursor (usually MOUSEX)
CURSORY y valuator attached to cursor (usually MOUSEY)
GHOST X x ghost valuator
GHOST Y y ghost valuator
TIMER0...TIMER3 Timer devices
Special Devices
Device Description
QFULL Creates event when device queue overflows

Polling a Device

You can poll a device to determine its current state.

getbutton Subroutine

The getbutton subroutine polls a button and returns its current state. The number parameter specifies the number of the device you want to poll. The getbutton subroutine returns either TRUE or FALSE. TRUE indicates the button is pressed. The syntax is as follows:

Int32 getbutton(Device number)

getdev Subroutine

The getdev subroutine polls up to 128 valuators and buttons at one time. You specify the number of devices you want to poll and an array of devices. (See the Input Buttons and Input Valuators tables for listings of devices.) The values parameter returns the state of each device in the corresponding array location. The syntax is as follows:

void getdev(Int32 number, Device *devices, Int16 *values)

getvaluator Subroutine

To determine the values of valuators, use the getvaluator subroutine. You can poll any valuator, whether it is queued or not. The device parameter specifies a valuator device number, whose value reflects the current state of the device. The syntax is as follows:

Int32 getvaluator(Device device)

Event Queue

Input devices can make entries in the event queue. Each entry includes the device number and a device value. The qdevice subroutine enables queuing of events from an input device. The unqdevice subroutine indicates that a device is no longer queued. The isqueued subroutine tells you if a specific device is queued. The three subroutines most commonly used for queuing are qdevice, qread, and qtest.

The input queue can contain up to 101 events at a time. To check for overflow, you can queue the QFULL device. This inserts a QFULL event in the graphics input queue of a GL program at the point where queue overflow occurred. This event is returned by the qread subroutine at the point in the input queue at which data was lost.

qdevice Subroutine

The qdevice subroutine queues the specified device (a keyboard, button, or valuator). The device parameter specifies a device name. Each time the device changes state, an entry is made in the event queue. The syntax is as follows:

void qdevice(Device device)

qtest Subroutine

The qtest subroutine returns the device number of the first entry in the event queue; if the queue is empty, the subroutine returns zero. The qtest subroutine always returns immediately to the caller and makes no changes to the queue. The syntax is as follows:

Int32 qtest()

qread Subroutine

The qread subroutine, like the qtest subroutine, returns the device number of the first entry in the event queue. However, if the queue is empty, the subroutine waits until an event is added to the queue. The qread subroutine returns the device number, writes the data part of the entry into data, and removes the entry from the queue. The syntax is as follows:

Int32 qread(Int16 data)

qreset Subroutine

The qreset subroutine removes all entries from the event queue and discards them. The syntax is as follows:

void qreset()

Polling and Queuing Example Program

The following C language code uses both polling and queuing to control a simple paint program. To determine the color, the program reads characters typed from the keyboard. To determine the drawing location, the program polls the LEFTMOUSE device and draws a 5-pixel-wide circle if the value for the device is TRUE.

 while (TRUE) {
  while (qtest() || !attached) {
   dev=qread(&value);
   if (dev == ESCKEY) {
    exit(0);
   }
   else if (dev == REDRAW) { 
   /* if first in queue */
    reshapeviewport();
    color (BLUE);
    clear();
   }
   else if (dev == RKEY) {
    color(RED);
   }
   else if (dev == GKEY) {
    color(GREEN);
   }
   else if (dev == BKEY) {
    color (BLUE);
   }
   else if (dev == INPUTCHANGE) attached = value; 
  }  /*end of while qtest or not attached */
  mdraw();
 } /* end of while (TRUE) */
} /* end of main() */
mdraw() {
 int ix;
 int iy;
 if (getbutton(LEFTMOUSE)) {
  ix=getvaluator(MOUSEX);
  iy=getvaluator(MOUSEY);
  circfi (ix, iy, 5);
 }
}

This example assumes that you have initialized the program appropriately, especially regarding the use of the qdevice subroutine to enable the R, G, and B keys for queuing.

tie Subroutine

You can tie a queued button to one or two valuators so that whenever the button changes state, the system records the button change and the current valuator position in the event queue. The tie subroutine takes three parameters: button and two valuators, val1 and val2. The syntax is as follows:

void tie(Device button, Device val1, Device val2)

Whenever the button changes state, three entries are made in the queue that record the current state of the button and the current position of each valuator. You can tie one valuator to a button by making the val2 parameter equal to zero. You can untie a button from valuators by making both the val1 and val2 parameters equal to zero.

noise Subroutine

Some valuators are noisy; that is, they report small fluctuations in value, indicating movement when no event has occurred. The noise subroutine allows you to set a lower limit on what constitutes a move. The value of a noisy valuator must change by at least the value set in the delta parameter before the motion is significant. The noise subroutine determines how often a queued valuator makes entries in the event queue. For example, noise(v,5) means that the valuator specified in the valuator parameter must move at least five units before a new queue entry is made. The syntax is as follows:

void noise(Device valuator, Int16 delta)

qenter Subroutine

The qenter subroutine creates event queue entries. It places entries directly into the event queue. The qenter subroutine takes two 16-bit integers, given in the qtype and value parameters, and enters them into the event queue. The syntax is as follows:

void qenter(Int16 qtype, Int16 value)

unqdevice Subroutine

Use the unqdevice subroutine to disable the queuing of events from a device. If the device has recorded events in the queue that have not been read, those events remain in the queue. (You can use the qreset subroutine to flush the event queue.) The syntax is as follows:

void unqdevice(Device dev)

isqueued Subroutine

The isqueued subroutine indicates whether a specific device is queued. It returns a Boolean value. A value of TRUE indicates that the device is enabled for queuing; FALSE indicates that the device is not queued. The syntax is as follows:

Int32 isqueued(Int16 device)

blkqread Subroutine

The blkqread subroutine returns multiple queue entries. Its first parameter, data, specifies an array of short integers, and its second parameter, number, specifies the size of the array data. The blkqread subroutine returns the number of 16-bit integers stored in the array specified in the data parameter. The array is filled alternately with device numbers and device values. Because each queue entry consists of two 16-bit words, the number of entries read is twice the number of queue entries and cannot be more than the value of the number parameter. The syntax is as follows:

Int32 blkqread(Int16 *data, Int16 number)

You can also use this subroutine when only the last entry in the event queue is of interest; for example, when a user-defined cursor is being dragged across the screen and only its final position is significant.

Input Focus

Keyboard, mouse, and valuator events are added to the event queue only when the application window has input focus. Input focus is controlled by the window manager. Windows with focus are usually highlighted in some fashion (typically by changing the border color of the window).

Note: In a multiwindow application, only one of the application windows can have input focus at a time.

The default window manager for your system is the AIXwindows window manager. The behavior of this window manager can be controlled by appropriately editing the ./.Xdefaults file in the user's home directory. The focus policy is controlled by the keyboardFocusPolicy resource. If the following line is added to the .Xdefaults file:

Mwm*keyboardFocusPolicy: pointer

the window with the cursor in it has input focus. Alternatively, if the following line is added to the .Xdefaults file:

Mwm*keyboardFocusPolicy: explicit

the user must click with the left mouse button inside a window to give that window input focus.

Notes:

  1. The window focus affects how the MOUSEX and MOUSEY events are reported. In particular, if pointer focus is selected, mouse events are reported only when the cursor is inside one of the application's windows. If explicit focus is selected, mouse events may be reported, depending on which window has the focus, even if the cursor is outside any of the application's windows.
  2. The focus policy determines how INPUTCHANGE events are queued. An INPUTCHANGE event is queued when an application's window receives or loses input focus. If pointer focus is selected, an INPUTCHANGE event is queued when the cursor enters or leaves an application window. If explicit focus is selected, the INPUTCHANGE token is generated only when the user makes a focus change by clicking the mouse elsewhere.

Special Devices

This section discusses the five types of special devices:

Keyboard Devices

(See "Using the Keyboard".)

Timer Devices

The timer devices record an event every 60th of a second. You can use a timer device to synchronize a graphics program with a real clock. To record events less frequently, use the noise subroutine. For example, if you call:

noise (TIMER0, 30)

only every 30th event is recorded, so an event queue entry is made each half second.

Cursor Devices

The cursor devices are pseudo-devices that are equivalent to the valuators currently attached to the cursor. (See "Creating a Cursor" for more information.)

Ghost Devices

Ghost devices, GHOSTX and GHOSTY, do not correspond to any physical devices, although they can be used to change a device under program control. For example, to drive the cursor from software, use attachcursor(GHOSTX,GHOSTY) to make the cursor position depend on the ghost devices. Then use the setvaluator subroutine on GHOSTX and GHOSTY to move the cursor.

Window Manager Devices

The following devices can be queued by the user application to obtain window manager events. Some of these devices are queued automatically when a window is opened. Some have to be queued explicitly. All of these devices return the window ID of the window associated with the event. See "Creating and Managing Windows" for more information.

REDRAW The window manager inserts a redraw token each time a window becomes exposed and needs to be redrawn. The REDRAW device is queued automatically when a window is opened.
REDRAW events are generated for a window whenever the following events occur:
  1. the window is uncovered because another window has been moved away or pushed below it.
  2. the window has been resized smaller or larger by the user.
  3. whenever the window is moved.
In the current implementation, the contents of the z-buffer are not copied to the new location on a window move; therefore, a REDRAW event is generated out of necessity. In the current implementation, REDRAW events are not generated if the overlay portion of a window has been drawn into or otherwise affected by other windows, other GL applications, or the use of the fullscrn, endfullscrn subroutines. Currently, the REDRAWOVERLAY pseudodevice is not supported.
REDRAWICONIC The window manager sends this token when a window needs to be redrawn as an icon. The REDRAWICONIC device is queued automatically when the iconsize subroutine is called.
DEPTHCHANGE When queued, this device indicates an open window has been pushed or popped. The value of the token is the gid of the window that has changed. Use the windepth subroutine to determine the stacking order.

Note: The DEPTHCHANGE device is currently tied to the INPUTCHANGE device; DEPTHCHANGE events are only generated when INPUTCHANGE events are. DEPTHCHANGE events are reocrded only relative to the current process; changes of window stacking order involving other GL applications and/or X clients are not recorded.

WINSHUT When queued, the window manager sends this token when the Close item is selected from the window manager's title bar option menu. If the WINSHUT device is not queued, the Close item on the program's window menu appears grayed-out and has no effect if selected. Do not confuse the WINSHUT with the WINQUIT device. The WINSHUT device is used by the applications program to shut a window; the WINQUIT device is used to quit and exit the program.

Note: The WINSHUT device is not currently supported.

WINQUIT When queued, the window manager sends this token rather than killing a process when the Quit item is selected from the window manager's title bar option menu. If this device is not quit, the window manager issues a kill -15 command to the process ID of the process owning the window.
WINFREEZE If queued, the window manager sends this token when a window is stowed to icons, rather than blocking the processes of the stowed windows. This device should be queued if the program is designed to draw an icon (see the iconsize subroutine) or is a multiwindow application. In other words, if one window of a multiwindow application is stowed, this device allows the owner process to continue.
WINTHAW If queued, the window manager sends this token when a window is unstowed.
INPUTCHANGE The window manager inserts an INPUTCHANGE token when a window is given input focus. The value inserted with the token is the window ID of the window receiving focus. A value of 0 (zero) is returned if the window given focus belongs to another application. The INPUTCHANGE device is queued automatically when a window is opened.
PIECECHANGE If queued, this device indicates that a window has been exposed because another window has been moved away. This token is not sent if the window has been unstowed from an icon, or has been exposed due to a depth change.

Controlling Peripheral Input/Output Devices

The application programmer can set the initial value of a valuator device with the setvaluator subroutine.

setvaluator Subroutine

Valuators are single-value input devices: for example, the horizontal and vertical motion of mouse, or the turning of a dial. The value is a 16-bit integer. The setvaluator subroutine assigns an initial value (the init parameter) to a valuator. The min and max parameters specify the minimum and maximum values the device can assume. The syntax is as follows:

void setvaluator(Device val, Int16 init, Int16 min, Int16 max)

In addition to subroutines that poll and queue input devices, there are those that control the characteristics and behavior of the GL peripheral input/output devices. See "Using the Keyboard" for this information.


[ Next Article | Previous Article | Book Contents | Library Home | Legal | Search ]