LibGII API Manual

Steve Cheng

This document describes the application programming interface for LibGII, a flexible library for input. It is used by LibGGI.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


Table of Contents
Preface
1. Introduction
2. General
3. Library control
giiInit — Initialize and uninitialize LibGII
giiPanic — Exit LibGII programs for fatal errors
4. Input management
giiOpen — Open, join and close inputs
giiSetEventMask — set the types of events you want to see
giiEventPoll — wait for and receive events
giiEventSend — inject an event into the input
5. Event Structures
Key events
GGI keysym system
Pointer movement events
Pointer button events
Commands and information
Device information
Valuators
Expose events

Preface

There should not be any more changes to the LibGII/LibGGI API until the next major version. Unfortunately, implementation and documentation do not always match; if you encounter any such differences or have any other questions or comments on this documentation, please mail us at , or the GGI mailing list. Thank you.

For other developers: if you want to change this manual and do not know DocBook/SGML, just mail me the ASCII version and I will gladly format and include it for you.

This manual is primarily written as a reference to the user-visible API of LibGII. However, it is being expanded to cover basic graphics concepts as well. It will not be a full tutorial, as actual working code serves that function better. This manual is also not intended to be an LibGII internals guide, although implementation hints are dropped throughout the manual :)

This documentation is written in DocBook. The SGML source can be used to generate Unix manpages, HTML and text formats automatically.


Chapter 1. Introduction

LibGII (General Input Interface Library) is a flexible library for handling input from a variety of sources, including keyboards, mice, joysticks, etc.

LibGII consists of a main library (libgii.so) and a multitude of dynamic drivers. The library then loads the necessary "drivers" for the requested input.


Chapter 2. General

To use LibGII, #include ggi/gii.h in a C program.

Most LibGII functions return 0 to indicate success, and a negative error code to indicate errors. Return codes greater than 0 are usually additional hints or other non-negative integer data.

A list of error codes and descriptions can be found in the ggi/errors.h file, which is part of the LibGGI/LibGG package.


Chapter 3. Library control

giiInit

Name

giiInit, giiExit — Initialize and uninitialize LibGII

#include <ggi/gii.h>

int giiInit(void);

int giiExit(void);

Description

giiInit initalizes the library. This function must be called before using other LibGII functions; otherwise the results will be undefined.

giiExit uninitializes the library (after being initalized by giiInit) and automatically cleanup if necessary. This should be called after an application is finished with the library. If any GGI functions are called after the library has been uninitialized, the results will be undefined.

giiInit allows multiple invocations. A reference count is maintained, and to completely uninitialize the library, giiExit must be called as many times as giiInit has been called beforehand.

Return value

giiInit returns 0 for OK, otherwise an error code.

giiExit returns:

0

after successfully cleaning up,

> 0

the number of 'open' giiInit calls, if there has been more than one call to giiInit. As giiInit and giiExit must be used in properly nested pairs, e.g. the first giiExit after two giiInits will return 1.

< 0

error, especially if more giiExit calls have been done than giiInit calls.

Examples

Example 3-1. Initialize and uninitialize LibGII

if (!giiInit())
{
        exit(EXIT_FAILURE);  /* can't start! */
}

/* Do some libgii stuff */

giiExit();

giiPanic

Name

giiPanic — Exit LibGII programs for fatal errors

#include <ggi/gii.h>

int giiPanic(const char *format, ...);

Description

giiPanic does a graceful shutdown, with printf(3)-style reporting, taking a format string and any additional variables. It will close all inputs, print the given error message to stderr, and then exit the application.

giiPanic should only be used by usermode programs when something is really screwed, and they do not know what to do. The same applies for libraries, but might be used in rare situations such as corruption of critical data structures.

Return value

Never returns.

Examples

Example 3-1. An unrecoverable error


if (my_important_struct->magic != MAGIC) {
	giiPanic("Fatal error: magic corrupted\n");
}

Chapter 4. Input management

giiOpen

Name

giiOpen, giiJoinInputs, giiClose — Open, join and close inputs

#include <ggi/gii.h>

gii_input_t giiOpen(const char *input, ...);

gii_input_t giiJoinInputs(gii_input_t inp, gii_input_t inp2);

int giiClose(gii_input_t inp);

Description

giiOpen opens an input. This function is given the name of an input driver to load. Passing NULL here results in an auto-select mechanism, which currently means examining the contents of GII_INPUT.

The optional arguments are a NULL-terminated list of pointers, which are used to give additional information to the targets. Currently only the first pointer is specified: void* argptr, a pointer to a library-specific struct. It is used to pass parameters that are not easily transferable in textual form.

Parameters which can be represented in text format are usually transfered in the input parameter, in the format: library_name: arguments

giiJoinInputs joins two inputs into one. From a programmers' point of view, this closes both inp and inp2 and opens an new input that combines both inputs into one. That is, after giiJoinInputs has completed, there is no need to giiClose inp and inp2 any more. When cleaning up, you need to close the returned input instead. See the example for details. However the inputs are not actually closed or reopened internally. That is, you will not get any startup-events or similar the driver generates, though pending events of both old inputs are transferred to the newly created input.

giiClose releases and destroys an open input and its associated internal control structures. This will put back input streams to their default modes, etc.

Important: If you want to handle input while also using LibGGI, using LibGII functions such as giiOpen is almost certainly not what you want. Use LibGGI functions such as ggiEventRead(3) with the LibGGI visual instead.

Return value

giiOpen and giiJoin return the opened or joined input (gii_input_t), or NULL for error.

giiClose returns 0 for OK, otherwise an error code.

Examples

gii_input_t inp,inp2;

/* Initialize the GII library. This must be called before any other
 * GII function. */
if (giiInit() != 0) exit(1);

/* Open the nulldevice for testing ... */
if ((inp=giiOpen("input-null",NULL)) == NULL) {
        giiExit();
        exit(1);
}
/* Open stdin for testing ... */
if ((inp2=giiOpen("input-stdin",NULL)) == NULL) {
        giiExit();
        exit(1);
}
/* Now join them. Note the usage of _i_n_p_=_giiJoin(inp,inp2);
 * This is the recommended way to do this. */
inp=giiJoinInputs(inp,inp2);
/* Note that this mends inp2 into inp. That is you may not call
   giiClose(inp2) - this happens together with giiClose(inp) ! */

... do the real work here ...

/* Close the joined input */
giiClose(inp);

/* Now close down LibGII. */
giiExit();

See Also

giiSetEventMask

Name

giiSetEventMask, giiGetEventMask, giiAddEventMask, giiRemoveEventMask — set the types of events you want to see

#include <ggi/gii.h>

int giiSetEventMask(gii_input_t inp, gii_event_mask evm);

gii_event_mask giiGetEventMask(gii_input_t inp);

int giiAddEventMask(gii_input_t inp, gii_event_mask mask);

int giiRemoveEventMask(gii_input_t inp, gii_event_mask mask);

Description

giiSetEventMask sets the mask of events you want to receive. Keep that down to those you really handle, as this allows to save time and memory by skipping checks and not allocating queues for events you will never read out.

giiGetEventMask lets you query the currently set mask.

giiAddEventMask and giiRemoveEventMask are macros that set or delete individual bits in the bitmask.

Return value

giiSetEventMask, giiAddEventMask and giiRemoveEventMask return 0 on success or an error code otherwise.

giiGetEventMask returns the currently set mask.

giiEventPoll

Name

giiEventPoll, giiEventSelect, giiEventsQueued, giiEventRead — wait for and receive events

#include <ggi/gii.h>

gii_event_mask giiEventPoll(gii_input_t inp, gii_event_mask mask, struct timeval *t);

int giiEventSelect(gii_input *inp, gii_event_mask *mask, int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

int giiEventsQueued(gii_input_t inp, gii_event_mask mask);

int giiEventRead(gii_input_t inp, gii_event *ev, gii_event_mask mask);

Description

giiEventPoll waits for specific events to become available on an input. This call somewhat resembles the Unix select(2) call, but only for LibGII events and is more portable. This function is given the input to wait on, a mask of events, any of which will terminate the waiting, and a timeout t, after which the waiting will cease anyway. In case an event arrives, the timeout value is updated to the time that would have been remaining. So make sure to re-setup this value, when calling giiEventPoll in a loop.

giiEventSelect is the combination of giiEventPoll and select(2) allowing to wait for both LibGII events and arbitrary file descriptors in any of the three states. However, this function is not available if the operating system does not support the select(2) call, not even as a stub.

giiEventsQueued returns the number of events matching the specified event mask that are currently queued in the input.

giiEventRead blocks for and transfers an event from the given input to the location pointed to by ev. The event with the earliest timestamp that matches the given mask is returned to the application.

Return value

giiEventPoll returns a mask of available events (constrained by the given mask). It is 0 if no events are available. On error, a negative error code is returned.

giiEventSelect returns the same values as select(2). Unlike other LibGGI/LibGII functions, it also uses errno. It will update the timeout regardless of whether or not the system call does so.

giiEventsQueued returns the number of events.

giiEventRead returns the size of event on success, and 0 on error.

giiEventSend

Name

giiEventSend — inject an event into the input

#include <ggi/gii.h>

int giiEventSend(gii_input_t inp, gii_event *ev);

Description

giiEventSend injects an event into the queue. Such events can be identified by (event->any.origin == GII_EV_ORIGIN_SENDEVENT). There are three main uses for this function:

  • "Simulating" input for independent subprograms.

  • Sending events to externally attached programs via specialized "inputs", that are actually rather "outputs".

  • Sending command events to inputs, like querying the axis of a valuator device.

Return value

giiEventSend returns 0 on success, or an error code otherwise.

See Also


Chapter 5. Event Structures

All of the event structures are included by ggi/events.h.

Events are of type gii_event. It is a union of all of the LibGII event structures:

typedef union gii_event {

        uint8                   size;           /* size of this event   */

        gii_any_event           any;            /* access COMMON_DATA   */
        gii_cmd_event           cmd;            /* command/information  */
        gii_expose_event        expose;         /* exposure event       */
        gii_val_event           val;            /* valuator change      */
        gii_key_event           key;            /* key press/release    */
        gii_pmove_event         pmove;          /* pointer move         */
        gii_pbutton_event       pbutton;        /* pointer buttons      */

} gii_event;

All of the event structures begin with COMMON_DATA, which contains housekeeping information:

#define COMMON_DATA  \
        uint8   size;           /* size of event in bytes       */\
        uint8   type;           /* type of this event           */\
        sint16  error;          /* error (for replies)          */\
        uint32  origin;         /* origin device (etc)          */\
        uint32  target;         /* target device (etc)          */\
        struct timeval time     /* timestamp                    */

size

specifies the size of the given event (in bytes). Note that size is also accessable as the first member of gii_event as well.

type

is an enumeration of the possible types of LibGII events:

typedef enum gii_event_type {

        evNothing = 0,  /* event is not valid. (must be zero)   */

        evCommand,      /* report command/do action             */
        evInformation,  /* notification of new information      */

        evExpose,       /* exposure event                       */
        /* empty slot */

        evKeyPress=5,   /* key has been pressed                 */
        evKeyRelease,   /* key has been released                */
        evKeyRepeat,    /* automatically repeated keypress      */

        evPtrRelative,  /* pointer movements reported relative  */
        evPtrAbsolute,  /* pointer movements reported absolute  */
        evPtrButtonPress,       /* pointer button pressed       */
        evPtrButtonRelease,     /* pointer button released      */

        evValRelative,  /* valuator change (reported relative)  */
        evValAbsolute,  /* valuator change (reported absolute)  */

        evLast          /* must be less than 33                 */

}  gii_event_type;

Thus, by analyzing the contents of any.type, you can determine what the given event is, and select the appropriate member of the gii_event union to access to get at the event data.

error

is mainly there to round things up to a 32 bit boundary, but could be used to signal an error in a send-reply sequence.

origin

is a device handle; it distinguishes one input device from another, other than that there's no real meaning to the number.

target

is also a device handle, but for distinguishes input devices when sending events to an input device (e.g. via giiEventSend).

time

indicates when the event in question has been generated.


Key events

The gii_key_event structure represents key/button events from keyboards and other devices.

Event types:

evKeyPress
evKeyRepeatevKeyRelease

/*      key events should be used to report events obtained from keys and
**      other switches.
*/
typedef struct gii_key_event {

        COMMON_DATA;

        uint32  modifiers;      /* current modifiers in effect  */
        uint32  sym;            /* meaning of key       */
        uint32  label;          /* label on key         */
        uint32  button;         /* button number        */

} gii_key_event;

effect

specifies the modifiers currently in effect, for example, the shift keys on a keyboard.

sym

is the 'symbol' of the key, describing the resultant character produced by the key. This is roughly the 'label' on the key (described below) combined with the effect.

label

is the actual label which is present on the key in question, and the main 'symbol' on the key. label can be used as a generalized, portable keycode or scancode of the key.

button

is the button number distinguishing between the different buttons on the device. For example, on a keyboard it is a number from 0 to 127 (i.e. a 'scancode'), on a joystick it might be 1 to 4, and on a spaceorb it will be 1 to 8.

In GGI, key values and characters are specified in accordance to ggi/keyboard.h. They are organized in a similar way to Linux keysyms (but without the braindamage) and Unicode. However, in the GGI system, no key is guaranteed to exist; the key values are for identification only. Particularly, applications should not rely on their presence. Also, because not all keyboards are configured in the same way, GGI application are encouraged to allow user configuration of the keys used and not hardcode them.


GGI keysym system

A list of GGI keysyms and some macros for manipulating them are found in gii/keyboard.h.

To be done.


Pointer movement events

/*      This is used to report change of pointer position.
**      Depending on the event type, the values are either absolute
**      or relative.
*/
typedef struct gii_pmove_event {

        COMMON_DATA;

        sint32  x, y;           /* absolute/relative position   */
        sint32  z, wheel;

} gii_pmove_event;

The gii_pmove_event structure describes pointer motion in terms of the x, y, z coordinates and the 'wheel'. The motion described may be relative (offset from the current location) or absolute (a specific location on the 'screen'), depending on whether the event is of type evPtrRelative or evPtrAbsolute, respectively.


Pointer button events

/*      Button events are sent to report a change in pointer button
**      state.  Depending on the event type, the button is either being
**      pressed or released.
*/
typedef struct gii_pbutton_event {

        COMMON_DATA;

        uint32  button;         /* button number. This is a number, NOT a mask */

} gii_pbutton_event;

gii_pbutton_event simply specifies that the button is being pressed (type evPtrButtonPress) or released (type evPtrButtonRelease).

Pointer buttons are specified in order of common usage, with 1 being the primary button:

#define GII_PBUTTON_LEFT        1       /* Left or primary button */
#define GII_PBUTTON_PRIMARY     1
#define GII_PBUTTON_FIRST       1

#define GII_PBUTTON_RIGHT       2       /* Right/Secondary button */
#define GII_PBUTTON_SECONDARY   2
#define GII_PBUTTON_SECOND      2

#define GII_PBUTTON_MIDDLE      3       /* Middle or tertiary  */
#define GII_PBUTTON_TERTIARY    3
#define GII_PBUTTON_THIRD       3

Of course, applications should avoid hardcoding mouse button values.


Commands and information

gii_cmd_event is the basic structure for evCommand and evInformation events. It may need to be casted to some other structure (depending on code) to access the data.

#define GII_CMD_DATA_MAX  (248-sizeof(gii_cmd_nodata_event))

/*      These are used internally either to the application or the
 *      kernel. The same event is used for both Command and Information
 *      events. The recipient must not store references to the data. If
 *      the data information is needed afterwards, copy it!
 */
typedef struct gii_cmd_event {

        COMMON_DATA;

        uint32  code;                   /* command/request code */
        uint8   data[GII_CMD_DATA_MAX]; /* command related data */

} gii_cmd_event;


Device information

One use of evCommand is to convey some capabilities of a GII device:

/* This event is sent/received to require/get the capabilities of a device
 * as specified in target/origin.
 * An event stating num_buttons=num_axes=0 says, that the device is inactive,
 * unplugged, whatever. Devices automatically report (detectable) state
 * changes via devinfo. But you need to re-query the valinfo records.
 */
#define GII_CMDCODE_GETDEVINFO  (0x01)
typedef struct gii_cmddata_getdevinfo {

        char            longname[75];
        char            shortname[5];

        gii_event_mask  can_generate;

        int             num_buttons;    /* Maximum number of buttons. */
        int             num_axes;       /* Maximum number of axes. */

} gii_cmddata_getdevinfo;

This event is guaranteed to be generated immediately after opening an input source.

can_generate is a mask of all events that the device can generate. num_buttons and num_axes are the number of buttons and axes that the device can report on.


Valuators

To be done.


Expose events

If an application loses the focus and is not physically displayed (e.g. console switching, iconifying), it may be stopped. Some targets may implement a backbuffer and allow continuing, though.

After reactivation, the application will receive a redraw event, evExpose. This is its structure, describing the region which needs to be redrawn:

typedef struct gii_expose_event {

        COMMON_DATA;

        uint32  x,y;
        uint32  h,w;

} gii_expose_event;

Example 5-1. How to use

        ggi_event ev;

        /* ... wait and get the event... */

        if (ev.any.type == evExpose) {

                /* redraw part of screen... */
                redraw_screen(ev.expose.x, ev.expose.y,
                        ev.expose.w, ev.expose.h);
        }

        /* ... etc ... */