gpm-Linux 1.13

A general purpose mouse server for the Linux console

April 1997

by Alessandro Rubini (rubini@ipvvis.unipv.it)


Table of Contents


Overview

The gpm package is a mouse server for the Linux console. It is meant to provide cooked mouse events to text-only applications, such as editors and simple menu-based apps. The daemon is also able to repeat packets in "msc" format to a graphic application. This last feature is meant to override the single-open problem of busmice. The roots of gpm come from the `selection-1.5' package, by Andrew Haylett.

The first application to support the mouse has been "The Midnite Commander", by Miguel de Icaza. `mc-0.11' and later releases offer mouse support if you have the mouse server running on your system. The file `t-mouse.el' provides support for using the mouse from within Emacs. See section Emacs Support

As of release 0.96, a default-handler is released with gpm, and can be used to handle Control-Mouse events to draw menus on the screen. The gpm-root program, however, needs kernel 1.1.73 or newer. See section The "gpm-root" program

Release 1.00 has been an incompatible one (is is incompatible with releases older than 0.97), but is compatible with the kernel-level mouse driver (available as kmouse-x.xx.tar.gz from the mirrors of tsx-11.mit.edu. With 1.0 the high level library is available, together with a demonstration/test program. A small utility to help in detecting your mouse-type is also included.

Compiling and Installing

Just say `./configure && make && make install' to your shell. You'll need gpm installed to compile the latest release of The Midnait Commander with mouse support enabled.

Binaries are not released with the package because it's safer for you to compile the package by yourself.

Server Invocation

The gpm executable is meant to act like a daemon (thus, gpmd would be a better name for it). This section is meant to describe the command-line options for gpm, while its internals are outlined in the next section. See section Gpm Internals.

Due to restrictions in the ioctl(TIOCLINUX) system call, gpm must be run by the superuser. The restrictions have been added in the last 1.1 kernels to fix a security hole related to selection and screen dumping.

The server can be configured to match the user's taste, and any application using the mouse will inherit the server's attitude. Beginning from release 1.02, the mouse `feeling' can be reconfigured by each user logging on the system console. See the description of "-q" section Server Invocation.

As of 0.97 the server program puts itself in the background. To kill gpm you can just reinvoke it with the -k cmdline switch, although `killall gpm' can be a better choice.

Special Commands

Version 1.10 adds the capability to execute special commands on certain circumstances. Special commands default to rebooting and halting the system, but the user can specify his/her personal choice. The capability to invoke commands using the mouse is a handy one for programmers, because it allows to issue a clean shutdown when the keyboard is locked and no network is available to restore the system to a sane state.

Special commands are toggled by triple-clicking the left and right button -- an unlikely event during normal mouse usage. The easiest way to triple-click is pressing one of the buttons and triple-click the other one. When special processing is toggled, a message appears on the console (and the speaker beeps twice, if you have a speaker); if the user releases all the buttons and presses one of them again within three seconds, then the special command corresponding to the button is executed.

The default special commands are:

left button
Reboot the system by signalling the init process
middle button (if any)
Execute `/sbin/shutdown -h now'
right button
Execute `/sbin/shutdown -r now'

The -S commandline switch enables special command processing and allows to change the three special commands. To accept the default commands use `-S ""' (i.e., specify an empty argument). To specify your own commands, use a colon-separated list to specify commands associated to the left, middle and right button. If any of the commands is empty, it is interpreted as `send a signal to the init process'. This particular operation is supported, in addition to executing external commands, because sometimes bad bugs put the system to the impossibility to fork; in these rare case the programmer should be able to shutdown the system anyways, and killing init from a running process is the only way to do it.

As an example, `-S ":telinit 1:/sbin/halt"', associates killing init to the left button, going single user to the middle one, and halting the system to the right button.

System administrators should obviously be careful about special commands, as gpm runs with superuser permissions. Special commands are best suited for computers whose mouse can be physically accessed only by trusted people.

Command Line Options

Available command line options are the following:

-a accel
Set the acceleration value used when a single motion event is longer than delta (see -d).
-b baud
Set the baud rate.
-B sequence
Set the button sequence. "123" is the normal sequence, "321" can be used by left-handed people, and "132" can be useful with two-button mice (especially within Emacs). All the button permutations are allowable.
-d delta
Set the delta value. When a single motion event is longer than delta, accel is used as a multiplying factor. (Must be 2 or above)
-g number
With glidepoint devices, emulate the specified button with tapping. number must be 1, 2, or 3, and refers to the button number before the -B button remapping is performed. This option applies to the mman and ps2 decoding. No button is emulated by default because the ps2 tapping is incompatible with some normal ps2 mice
-h
Print a summary of command line options.
-i interval
Set interval to be used as an upper time limit for multiple clicks. If the interval between button-up and button-down events is less than limit, the press is considered a double or triple click. Time is in milliseconds.
-k
Kill a running gpm. This can be used by busmouse users to kill gpm before running X (unless they use -R or the single-open limitation is removed from the kernel).
-l charset
Choose the inword() look up table. The charset argument is a list of characters. `-' is used to specify a range and `\' is used to escape the next character or to provide octal codes. Only visible character can appear in charset because control characters can't appear in text-mode video memory, whence selection is cut.
-m filename
Choose the mouse file to open. It defaults to `/dev/mouse'.
-M
Enable multiple mode. The daemon will read two different mouse devices. Any subsequent option will refer to the second device, while any preceding option will be used for the first device. This option automatically forces the "repeater" (-R) option on.
-o lines
Toggle modem lines. The lines argument can be "dtr", "rts" or "both". This is needed for some strange serial mice.
-p
Forces the pointer to be visible while selecting. This is the behaviour of selection-1.7, but it is sometimes confusing. The default is not to show the pointer, which can be confusing as well.
-q
Quit after changing mouse behaviour. This is intended to allow users to change the mouse "feeling" (-a, -B, -d, -i, -l, -p, -r) without restarting the server. Since this needs root permissions, the system administrators can use the `set-uid' bits to enable/disable such capability. Changing mouse parameters is nonetheless only allowed from one of the virtual consoles. Options are transferred only for the first mouse.
-r number
Set the responsiveness. A higher responsiveness is used for a faster cursor motion.
-R
Causes gpm to act as a repeater: any mouse data received while in graphic mode will be produced on the fifo `/dev/gpmdata' in mouse-system protocol. This means that you can configure the X server to use that fifo as a mouse device. This option is useful for bus-mouse owners to override the single-open limitation. It is also an easy way to manage those stupid dual-mode mice which force you to keep the middle button down while changing video mode. The option is forced on by the -M option.
-s number
Set the sample rate for the mouse device.
-S commands
Enable special-command processing, and optionally specify custom commands as a colon-separated list. See above for a detailed description of special commands.
-t name
Set the mouse type. Use `-t help' to get a list of allowable types. See section Mouse Types.
-v
Print version information and exit.
-2
Force two buttons. This means that the middle button, if any, will be taken as it was the right one.
-3
Force three buttons. By default the mouse is considered to be a 2-buttons one, until the middle button is pressed. If three buttons are there, the right one is used to extend the selection, and the middle one is used to paste it. Beware: if you use the `-3' option with a 2-buttons mouse, you won't be able to paste the selection.

Bugs and Problems

The gpm server may have problems interacting with X: if your mouse is a single-open device (i.e. a bus mouse), you should kill gpm before strating X, or use the "-R" option (see above). To kill gpm just invoke gpm -k. This problem doesn't apply to serial mice.

Two instances of gpm can't run on the same system. If you have two mice use the "-M" option (see above).

While the current console is in graphic mode, gpm sleeps until text mode is back (unless -R is used). Thus, it won't reply to clients. Anyways, it is unlikely that mouse-eager clients will spur out in hidden consoles.

pre-1.0 gpm releases have problems with kernel 1.2.9 and later, because the clients must have write permission on the node /var/run/gpmctl. You should invoke chmod on the node or install gpm-1.0 or later (you have this docs, you have the updated software).

Gpm Internals

The server is organized as a main loop built around a select() system call. It responds both to mouse events and to input from the clients, which are connected to the server through a unix domain socket. The connection is used to tell the server what a client is interested in, and to get mouse events.

When no clients are connected to the active console, the server runs the selection mechanism (cut and paste of text). The election mechanism is a simple and well-designed application, whose behaviour can be cloned by clients, by telling the server to inherit the default response for certain mouse events (motion being the most interesting).

Events

Whenever the mouse generates an event, the event is dispatched to the active client for the current console, or to the default handler, if present. Otherwise selection is run. A default handler is a client process which gets mouse events form all the virtual consoles. See section Default Handlers.

When a client is involved, it is handled a Gpm_Event structure, built by the server. The fields for Gpm_Event are the following:

unsigned char buttons;
An or-mask of the values GPM_B_LEFT, GPM_B_MIDDLE and GPM_B_RIGHT. It corresponds to the state of the mouse buttons when the event is reported. The current implementation of gpm allows at most three buttons.
unsigned char modifiers;
The value of the kernel variable shift_state, as of `keyboard.c', when the event is reported. It is a bitmask value, and corrsponds to the least significant byte of the value used by the `loadkeys' program. Use of symbolic names in source code is available after inclusion of `<linux/keyboard.h>', as exemplified in `mev.c'.
unsigned short vc;
The number of the active virtual console when the event is reported. The client is not expected to use this value, which corresponds to the controlling terminal of the client process, unless it gets events form multiple consoles. See section Default Handlers.
short x, y;
The position of the mouse pointer where the event is reported. Is is 1-based, to be compatible with selection and libcurses.
short dx, dy;
The change in position since the last reported event.
enum Gpm_Etype type;
A bit-mask, representing the type of reported event, as described later. See section Event Types
int clicks;
A counter, which is valid at button-down, drag or button-up. It can be 0, 1 or 2 to mean single, double or triple click.
enum Gpm_Margin margin;
A bit-mask, telling if the pointer has gone out of the visible screen. The indivudual bits are named GPM_TOP, GPM_BOT, GPM_LFT, GPM_RGT. Only one of them is active at a time, to allow using switch on the value. Vertical outrun takes precedence on horizontal outrun. See section How margins are managed

How margins are managed

Motion and button-press events are constrained to remain within the visible screen. This means that the x will be within 1 and 80 and y will be within 1 and 25 when the console is 80x25 cells. However, a client can keep track of movements outside the screen, by using the dx and dy fields, which aren't subject to clipping.

The server helps applications in detecting margin conditions by filling the margin field. Whenever the pointer tries to cross screen boundaries, it is forced to remain on the border, but a flag is set in margin.

A different policy is in force for drag and button-release events. In this case the pointer is allowed to go outside the physical screen by exactly one position. This allows, for example, selecting to end of line by dragging down-left. The peculiar situation is nonetheless signaled through the margin flags. The client should be careful to fit the values within the screen if needed. See section Utility Functions.

Event Types

The type field int Gpm_Event is made up of bit-wide flags. The existing bit masks belong to two groups: bare events and cooked events. The bit-mask GPM_BARE_EVENTS is provided to extract bare events, by and-ing ('&') it with the type field. For any event, exactly one bit will be set in the resulting bitmask.

Bare events are the following:

GPM_MOVE
A motion event, with all buttons up.
GPM_DRAG
A motion event, but one or more buttons are kept pressed.
GPM_DOWN
A button press event. The buttons field will report which buttons are pressed after the event.
GPM_UP
A button release event. The buttons field will report which buttons are being released. Nothe that this is different from the previous case.
GPM_ENTER
This means "enter in the current Region of Interest", and such event can only happen if the high-level library is used. When the type is GPM_ENTER, all the other fields are undefined. See section High Level Library.
GPM_LEAVE
This is only delivered by the high level library, too. Events of type GPM_LEAVE have all other fields undefined.

Cooked events are the following:

GPM_SINGLE
This bit may be set at button-press, drag and button release events, and can be used to identify a single press. The time interval used to choose a double click from two single clicks is set by a parameter in the daemon (configurable at daemon invocation).
GPM_DOUBLE
Used to identify a double click (press, drag, release)
GPM_TRIPLE
Used to identify a triple click (press, drag, release)
GPM_MFLAG
The "motion flag" is true if some dragging happened between button-press and button-release. It can be used by those applications which respond to events at button release. It is available at drag and release.

Mouse Types

I chose to isolate anything related to mouse types, because I can't test them all. The source file mice.c is made up of type-specific functions, as well as a table to dispatch computation. The table offers a default device name for each mouse type as well, but I lack information about some of them. Contributions in this field are particularly welcome.

The mouse type is specified on command line with the "-t" option. The option takes an argument, which can be one of the following strings; two different strings are available sometimes: one is the old selection-compatible name, the other is the XFree name. If the second string is missing, it means XFree doesn't yet support the device, at least to my knowledge -- or it supports the device in a different way, like the Wacom tablet. I'll add compatible names when needed.

bare Microsoft
The microsoft protocol, without any extension. It only reports two buttons. If your device has three, you shoudl either try toggling the DTR and RTS lines ("-o" option) or invoke gpm with "-t msc" while keeping the middle button down. Silly, isn't it?
ms
This is the original microsoft protocol, with a middle-button extension. Some old two-button devices send some spurious packets, which can be misunderstood as middle-button events. If this is your case, use the bare mouse type. This decoder, however, is not able to decode drag event for the middle button. A more powerful "ms" decoder is in the source files but is disabled since it has problems with some mice. You can try to enable it and recompile the package, anyway.
msc MouseSystems
This is the standard protocol for three-button serial devices.
mman Mouseman
The protocol used by the new Logitech devices.
bm BusMouse
Some bus devices use this protocol, including those produced by Logitech.
logi Logitech
This is the protocol used by old serial Logitech mice.
ligim LogiMouse
This decoder tells Logitech mice to behave lice Msc ones. It is needed to run reliably some Logitech mice.
ps2 PS/2
The protocol used by most busmice.
mm MMSeries
Title says it all.
sun
The protocol used on Sparc computers and a few others.
ncr
This `type' is able to decode the pointing pen found on some laptops.
wacom
The protocol used by the Wacom tablet.
logim
Used to turn Logitech mice into Mouse-Systems-Compatible. Obviously, it only works with some of the Logitech mice.
pnp
This decoder works with the new mice produces by our friend Bill, and maybe with the old ones as well. The Pnp protocol is hardwired at 1200 baud and is upset by normal initialization.
ms3
A decoder for the new serial IntelliMouse devices, the ones with three buttons and a protocol incompatible with older ones.

Connection Details

Each virtual console has a stack of clients attached to it. They talk to gpm by writing to a control socket and get mouse events by reading it. All the clients in the stack can receive events. Gpm-1.10 and earlier only sent events to the top client, but sometimes users play with multiple programs using suspend-resume (thanks Ian).

In addition to the per-console stacks, another stack is there to store default-handling clients. xref See section Default Handlers.

Each client registers with the server and tells which events it is interested in. Events not managed by the client can be handled by the selection mechanism, which is compiled in the server itself. This approach simplifies writing clients which respond only to button press/release events, because highlighting the mouse pointer can be performed by the server. A default handler in turn can respond only to mouse events associated with modifier keys, so that selection is used for any mouse-only event.

Clients are required to fill a Gpm_Connect structure and pass it to the server. The structure is made up by four unsigned int fields. See section Connecting and Disconnecting. @tindex Gpm_Connect

eventMask
A bitmask of the events the client wants to receive. Both bare and cooked events are allowed to appear in the mask.
defaultMask
A mask to tell wich events allow a default treatment (the selection one). These are mouse events, independent of the modifier keys.
minMod
The minimum amount of modifiers required by the client. This field is used for default-handlers which manage control-mouse events whithout interfering with mouse-only ones. See section Default Handlers.
maxMod
The maximum amount of modifiers the client is willing to receive. Events featuring a modifier key not included in maxMod won't be passed to the client.

Two more fields are there to tell about the connection itself, and you're not asked to fill them, because Gpm_Open will do it for you.

int pid
The pid of the connecting application.
int vc
Which virtual console to gain control of.

Keyboard modifiers are used to multiplex clients on the same virtual console. You (as a programmer) don't need to care about the internal workings (which are detailed in ref See section Default Handlers), but only need to choose the right values for your application.

Ecamples:

minMod=0; maxMod=0;
specifies a client which senses mouse-only events, but neither shift-mouse nor alt-mouse nor control-mouse.
minMod=0; maxMod=~0;
is a client which gets any mouse event.
minMod=1<<KG_SHIFT; maxMod=1<<KG_SHIFT;
is a client which senses all shift-mouse events and nothing more.
minMod=1<<KG_SHIFT; maxMod=~0;
is a client interested in shift-and-whatever-else mouse events, but disregarding mouse-only events.

If the modifier keys in the event are too few or too many, the event won't be reported to the client. If the modifiers are right but the current event is not part of the eventMask, it is not reported as well. If the event is not used by the client, it can nonetheless be passed to another client (a default handler or the internal selection mechanism), according to the defaultMask. If the event has been already reported to the current application, it will also be passed along the chain, if the GPM_HARD bit is set the defaultMask.

Good values for defaultMask can thus be the following:

0
To sink any event, even those I don't use.
~eventMask
Pass along any event I don't use.
~GPM_HARD
Just the same, independently of eventMask.
GPM_MOVE|GPM_HARD
Pass motion events, even if I use them. This is the good choice for an application which wants information on mouse motion, but leaves the task of cursor-drawing to the server.

Default Handlers

In addition to console-specific clients, gpm allows for console-independent clients -- those clients which handle events ignored by conventional clients

Keyboard modifiers are used to multiplex the different clients on the same console, and a default handler should specify a non-zero minimum modifier set.

To summarize, events which get to the server can be delivered to the following "clients", orderly:

* The current client for the current console, if any.

* The default handler, if any.

* The builtin `selection' mechanism.

A keyboard modifier which connected with a minMod equal to the "Control" modifier and a maxMod of ~0 (all bits on), will then get any event including the control key, if the application disregards it.

This means that if the foreground application gets only the "Meta" key, control-mouse is sufficient to invoke the default handler. If the application gets control-mouse but disregards "Meta", conversely, meta-control-mouse will invoke the default handler, and meta-mouse will be delivered to selection.

Both the minMod and maxMod fields are bitmasks, and their values are bitwise or-ed and and-ed with the current modifier mask.

gpm-root is an example of default handler. It gets control-mouse events by default, and reads user-specific conficuration files in order to draw menus on the background of your screen. See section The "gpm-root" program.

The Client Library

The libgpm.a archive is meant to provide the mouse protocol at different levels of abstracion. Applications linking to the gpm server are expected to benefit from using the library, as compared to managing the raw socket interface. Any source file using the library should include <gpm.h> to get gpm specific macros and prototypes.

Delivery of events within the library makes heavy use of the concept of "Handling Function" (or "handler", for short).

Handling Functions

A mouse handler is a function which registers itself within the library, and is called whenever a mouse event is reported to the application. It is passed two arguments and returns an integer value, according to the following typedef:

typedef int Gpm_Handler(Gpm_Event *event, void *clientdata);

The event is used to instantiate the mouse event just received, and the clientdata pointer is needed to implement some higher level functionality. An handler will be tipically invoked by Gpm_Getc, or by the high-level library, and the following discussion assumes the invoking function is Gpm_Getc (the high-level library only runs on behalf of Gpm_Getc).

Handling functions can do whatever they want to, and return to the caller an integer value, which can be used to generate a keyboard event. This feature is useful in that often the mouse is a shortcut for something which could be made by means of the keyboard.

The application main loop can detect if the keyboard event is a physical or generated one by looking at the global variable gpm_hflag, which is not zero only for handler-generated events.

An handling function can generate more than one key in response of a single mouse event. If it sets the global variable gpm_morekeys to a non-zero vairable before returning, it will be invoked again without waiting for mouse events. You can use gpm_morekeys as a counter of how many times you want to be called again -- the client library only compares it to zero.

The return value from an handler is used as follows:

EOF
This value is used to signal a fatal error, and will cause Gpm_Getc to return the same value to the caller, after setting gpm_hflag to 1.
0
A zero return value means that Gpm_Getc should go on as before, without returning to the caller. The event has been eaten by the handler and no key-press is simulated.
anything-else
Any other value is considered a "simulated" character, and is returned to the caller after setting gpm_hflag. This allows a quick way to implement yes/no boxes abd simple menus without interfering with the main body of an existing application. Moreover, if return values greater than 255 are used a single switch loop can parse both keyboard and mouse events.

A mouse handler is passed as second argument the content of the gpm_data variable, i.e. the current clientdata. The clientdata is almost unuseful unless you use the high-level library, because it holds a static value. Delivering the clientdata however allows the high-level management of mouse events to be a superset of the low-level code, rather than an incompatible alternative.

Low Level Library

The library offers utility functions to establish the connection and to get mouse events. They are designed to work painlessly if the server is not running on the host machine. Xterm support is available as well. See section Running under xterm.

Global Variables

This is the list of all the global variables present in the client library:

int gpm_flag
Initially zero, it is used to tell if the process is connected with a mouse server or not. It is used as a counter to manage multiple opens as well.
int gpm_tried
A flag, used to avoid retrying a connection if the server is not available on the system.
int gpm_fd
Initially -1, it is the file descriptor used to talk with the server. If we run under xterm, it will be -2.
int gpm_zerobased
Since selection and curses has always been one-based, this variable, zero by default, can be used to trigger zero-based coordinates in event reporting. It must be set before opening the mouse connection, and never changed later.
int gpm_visiblepointer
If not zero, causes the mouse cursor to be always visible on the window. It is zero by default.
gpm_mx
gpm_my
These variables (max X and max Y) are used when fitting events inside the screen. They are initalized by Gpm_Open, and never touched any more. If your application installs a signal handler for SIGWINCH, it should modify these variables. I don't want the client library to install a signal handler (although 1.11 handlet TSTP).
int gpm_hflag
Used to signal if a character has been generated by a mouse handler. See section Handling Functions
Gpm_Handler *gpm_handler; void *gpm_data
Both initially NULL, they're used to setup asynchronous mouse handling, as described below under the Gpm_Getc() item.
gpm_morekeys
Used by the mouse handler to provide more than one key: if gpm_morekeys is not zero, Gpm_Getc will invoke the handler without waiting for events. gpm_morekeys is never set by the mouse library.

Connecting and Disconnecting

Function: int Gpm_Open (Gpm_Connect *conn, int flag);

Open a connection with the server. The conn parameter points to the connection information for the being-created connection, as already described. It is passed to the server after filling the pid and vc fields.

flag should be 0 for normal applications, those interested in events related to their own console. The own console is considered to be the one attached to stdin, and it must match the string `/dev/tty*'. A negative value for flag is used to make the invoking application a default handler section Default Handlers, while a positive value is used to force connection to a particular console, either for debugging issues or whenever stdin is not a tty when Gpm_Open is invoked.

Multiple opens are allowed, and a stack of Gpm_Connect structures is managed by the library. You can, thus, re-open the connection in order to temporarily change the range of events you're interested in. When you invoke an external program, for example, you should re-open the connection with eventMask zeroed, and defaultMask, minMod and maxMod all equal to ~0.

The return value is either -1 or the file descriptor used to communicate with the server. When run under xterm, a gpm client gets event through stdin, and the return calue for Gpm_Open() will be -2. This value is always available withing gpm_fd.

Function: int Gpm_Close (void);

Pops the connection stack. It is used to restore the previous situation after a change in the connection masks. Closes the actual connection when the stack gets empty. On last close it returns 0, -1 otherwise.

Getting Events

Function: int Gpm_GetEvent (Gpm_Event *event);

Reads an event form gpm_fd. It should be called only when the gpm_fd descriptor is reported as readable by a select() system call, or it will block until an event arrives (unless you put the mouse file in non-blocking mode). It returns 1 on success, -1 on failure, and 0 after closing the connection. Failure can happen if a signal interrupted the read system call. This function doesn't work with xterm mouse reporting and is meant for internal use by the library.

Function: int Gpm_Getc (FILE *f);
Function: int Gpm_Getchar (void);

These are intended to be replacements for getc() and getchar() to be used by applications which are interested in the mouse. Their external behaviour is the same as getc(), but a mouse handler gets invoked whenever an event is available. See section Handling Functions. A mouse handler can force Gpm_Getc to return a specific value to the caller, and the "simulated" character is signaled by setting gpm_hflag to 1.

Function: int Gpm_Wgetch (WINDOW *win);
Function: int Gpm_Getch (void);

These are intended to be replacements for wgetch() and getch() to be used by applications which are interested in the mouse. They are the curses equivalent of Gpm_Getchar.

Utility Functions

Function: int Gpm_Repeat (int millisecs);

It returns 1 if no mouse events arrive in the next millicecs milliseconds, 0 otherwise. It is meant to be used by those handlers which need to repeat an action as long as the mouse button is pressed (while(Gpm_Repeat(200))...).

Function: int Gpm_DrawPointer (int x, int y, int fd);
Function: int GPM_DRAWPOINTER (Gpm_Event *ePtr;)

These are actually macros. They should be used to draw the mouse pointer after mangling the screen (while dragging on a menu, say), because letting it to the server won't work nicely, due to lack of synchronism between client and server. The file descriptor should refer to the console. The return value is 0 on success and -1 on failure. Gpm_DrawPointer is obsolete, and is retained only for compatibility.

Function: int Gpm_FitValuesM (int *x, int *y, int margin);
Function: int Gpm_FitValues (x,y);
Function: Gpm_FitEvent (ePtr);

The first is a function, while the other are macros. Note that Gpm_FitEvent does not return values. These three procedures should be used to fit the pointer inside the visible screen. They are needed for drag and release event. A connection bit will be available in the future to force the pointer in the visible region.

Note that fitting uses gpm_mx and gpm_my, which you should update when necessary. See section Global Variables.

Extra Functions

Function: char *Gpm_GetLibVersion (int *where);

This function returns a pointer to a static storage representing the version number of the library. It is only available from 0.98.2 onward, and returns a string like ""0.98.2"". The third number is optional, and the second number will always be reported as two digits; thus 1.10 is newer than 1.01. The where pointer, if not null, is used to store a decimal number representing the version -- 0.98.2 is 9802 and 1.1.8 is 10108.

Function: char *Gpm_GetServerVersion (int *where);

This function returns a pointer to a static storage representing the version number of the server. The version is retrieved through popen(), so it could fail (and return NULL)if no gpm program is in the current path. Alternatively, it could fail (and return a wrong value) if the gpm in the path is not the currently running one. The function is only available in the clientlibrary version 0.98.2 or newer, but it works with any daemon, from 0.01 onward. The string returned can be parsed in the same way as for Gpm_GetLibVersion(). A preparsed version is stored in *where if where is not null. Both these functions do their calculations only the first time they are invoked.

Function: int Gpm_GetSnapshot (Gpm_Event *ePtr);

This function gives a non-blocking snapshot of the current situation: it returns the number of mouse buttons, as known to the server, or -1 if that information is not available (under Xterm, or before connecting). If ePtr is not null, it is filled with information about the current state of the mouse. The fields have the following meaning: x,y: current position of the cursor; dx,dy size of the window; vc,modifiers the current console and the current shift state; buttons which buttons are currently help down; clicks the number of clicks (0,1,2). This function is only available from 0.98.2 onward, and will return -1 if run with an older server.

Since this information travels on the same file descriptor as the events, and applications usually don't want to lose events, the function returns 0 if the input queue is not empty.

High Level Library

The high level library is part of the main libgpm.a, but it acts at a different level of abstraction. The high level library depends in the lowe-level one, so if you link your application with any object of the high-level library, you're forced to link in the low-level one too.

If your application runs under xterm, however gpm-xterm offers all the needed functionality.

The main role of the high-level library is to define a way to manage windows (or "Regions of Interest" on your text screen). The regions are arranged in a stack, and event are delivered to the different windows according to their position both on the stack and on the screen. See section hltest.

Concepts

The high-level library is completely independent of the low-level one, so it used gpm_handler and gpm_data as connection point with Gpm_Getc().

All the functionality is based on the concept of RoI's. each RoI is descripted by a Gpm_Roi structure, which is made up by the following fields:

short xMin, xMax
These numbers identify the upper-left corner of the region. When events are reported to the region, the event coordinate will be relative to this position (zero-based).
short yMin, yMax
These numbers identify the lower-right corner of the region.
unsigned short minMod, maxMod
These modifier masks have the same role within the application as the same fields have in inter-application multiplexing.
unsigned short eventMask
It is the mask of events which are to be reported to the current region.
unsigned short owned
This is a bit, used to know if the region is owned by the library or the application, in order to issue free(0 when needed.
Gpm_Handler *handler
The function to be called when events are to be reported to the current region.
void *clientdata
The clientdata to be passed to the handler
Gpm_Roi *next, *prev
Links to the RoI chain.

Variables

Gpm_Roi *gpm_roi
The linked list of regions (pointer to the top one).
Gpm_Roi *gpm_current_roi
The region which got the last event (used to generate enter and leave events).
Gpm_Handler *gpm_roi_handler
This variabel is meant to be set by the user. It is the catch-all region of interest, which will be called for any mouse event not falling within any registered region. If NULL, the event will be discarded.
void *gpm_roi_data
the client data to be passed to gpm_roi_handler.

Functions

Function: Gpm_Roi *Gpm_PushRoi (int xmin, int ymin, int xmax, int ymax,
int mask, Gpm_Handler *fun, void *xtradata);

This function pushes a Region of Interest on top of the stack, after allocating it and filling with the provided values. fun is the function which will be called in order to handle events, and the roi itself will be passed to the function as clientdata. The Roi is represented by a struct Gpm_Roi structure, described in gpm.h. The xtradata field will be used to fill the xtradata field in Gpm_Roi. the return value is the Roi just pushed (i.e. the top of stack).

Function: char *Gpm_UseRoi (Gpm_Roi *roi);

While Gpm_PushRoi has to allocate the Region before pushing it, this function passes a pre-allocated function to the stack manager. The return value is the Roi just used.

Function: Gpm_Roi *Gpm_PopRoi (Gpm_Roi *roi);

Used to extract a Region of Interest from the stack, this function will also clear the Region if it is needed.

Function: Gpm_Roi *Gpm_RaiseRoi (Gpm_Roi *which, Gpm_Roi *before);

Raise the specified roi, either before the second Roi or at top-of- stack (if before is NULL). The return value is the new top-of-stack.

Function: Gpm_Roi *Gpm_LowerRoi (Gpm_Roi *which, Gpm_Roi *after);

Lower the specified roi, either after the second Roi or at bottom-of- stack (if before is NULL). The return value is the new top-of-stack.

Function: Gpm_Roi *Gpm_HandleRoi (Gpm_Event *ePtr, void * clientdata);

This function, which should not be invoked by the user, is the dispatching manager within the application for mouse events. This function will browse the stack of regions of interest in order to notify windows about Enter and Leave events (if they are interested in them), and then delivers the current event to the relevanto Roi.

If no Roi is interested in he event the *gpm_roi_handler function is invoked (if not null), with null clientdata.

Reported events are all those in Gpm_Event, and also GPM_ENTER and GPM_LEAVE. These can be used to toggle highlighting on a button or to drop a menu if the menubutton is entered during a drag. Remember that when Enter or Leave is notified, no other information in the event item should be used.

Running under xterm

As of release 0.18, gpm-based applications can run under xterm without any need for recompilation. The library is designed to convert xterm mouse events to gpm-style structures, so that the client will get the same events it got under the Linux console. Moreover, a source file (gpm-xterm.c) is available to mimick libgpm under a different OS than Linux. Porting to other text-based consoles is an open issue, but I myself have Linux alone.

The goal is to provide a uniform mouse interface with both xterm and the Linux console. Some features of libgpm would not be available, but if you run under xterm you know what you get, so you couldn't use them on the console anyway.

The sample directory in the distribution tree is meant to show how a simple mouse-sensitive application can be easily autoconfigured and compiled. The rmev program has proved to compile and run smoothly under Linux (both with and without libgpm.a), SunOS-4, Solaris-5, hpux-8.x and Ultrix-3.0.

Demonstration Clients

mev

The mev program is modeled after xev. It prints to stdout the console events it gets, both keyboard and mouse events.

mev's default behaviour is to get anything, but command line switches can be used to set the various fields in the Gpm_Connect structure, in order to customize the program's behaviour. I'm using mev to handle mouse events to emacs See section Emacs Support.

Command line switches for mev are the following:

-C number
Select a virtual console to get events from. This is intended to be used for debugging.
-d number
Choose a default mask. By default the server gets any events not belonging to the event mask. The mask can be provided either as a decimal number, or as a symbolic string.
-e number
Choose the event mask. By default any event is received. The mask can be provided either as a decimal number, or as a symbolic string.
-E
Enter emacs mode. In emacs mode events are reported as lisp forms rather than numbers. This is the format used by the t-mouse package within emacs.
-f
Fit events inside the screen before reporting them. This options re-fits drag events, which are allowed to exit the screen border, See section How margins are managed.
-i
Interactive. Accepts input from stdin to change connection parameters.
-m number
Choose the minimum modifier mask. Any event with fewer modifiers will not be reported to mev. It defaults to 0. The mask must be provided either as a decimal number, or as a symbolic string.
-M number
Choose the maximum modifier mask. Any event with more modifier than specified will not be reported to mev. It defaults to \~0, i.e. all events are received. The mask must be provided either as a decimal number, or as a symbolic string.
-p
Requests to draw the pointer during drags. This option is used by emacs to avoid invoking ioctl() from lisp code.

When the arguments are not decimal integers, they are considered lists of alphanumeric characters, separated by a single non-alphanumeric character. I use the comma ",", but any will do.

Allowed names for events are `move', `drag', `down' or `press', `up' or `release', `motion' (which is both `move' adn `drag'), and `hard'.

Allowed names for modifiers are `shift', `leftAlt', `rightAlt', `anyAlt' (one or the other), `control'.

When the `-i' switch is specified, mev looks at its standard input as command lines rather than events. The input lines are parsed, and the commands `push' and `pop' are recognized.

The `push' command, then, accepts the options `-d', `-e', `-m' and `-M', with the same meaning described above. Unspecified options retain the previous value and the resulting masks are used to reopen the connection with the server. `pop' is used to pop the connection stack. If an empty stack is popped the program exits.

The only other commands recognized are `info', used to return the stack depth, and `quit' to premautrely terminate the program.

sample/rmev

rmev is a reduced version of mev, but it is designed to be as portable as possible. It uses a subset of the capabilities of libgpm.a, but works smoothly on both xterm and the Linux console. It is distributed with gpm to show how a curses based application can support the mouse with a small effort. Most of the xterm decoding is by Janne Kukonlehto. See section Running under xterm.

Emacs Support

Emacs support is quite complete as of 0.14. The enclosed file t-mouse.el, also available in byte-compiled form, is used to pass mouse events to emacs. t-mouse.elc is installed in the lib/emacs/site-lisp directory of the install tree (by default /usr).

Events with modifiers other than Meta are not managed by the library. Mouse-only and meta-mouse events are passed to the lisp program, which converts them to be similar to X mouse events inside emacs. Actions are then invoked through a local keymap.

In my own environment I can use mouse-only and meta mouse within emacs, shift-mouse to run selection and control-mouse to run gpm-root. See section The "gpm-root" program.

I suggest to put the following form in your own .emacs file, to avoid loading t-mouse when you aren't working on the Linux console:

(if (and (string-match ".*-linux" system-configuration)
         (or (string-match "linux" (getenv "TERM"))
             (string-match "con.*" (getenv "TERM"))))
    (load-library "t-mouse"))

Mouse events are dispatched through the keymap t-mouse-keymap, which tries to mimick the behaviour of emacs under X.

The scrollbar sits on the last column of the screen, though it is not visible. When you click on the last column, a scroll-bar action is taken. If this annoys you, please let me know.

If you kill the `gpm' server, Emacs won't respond to mouse events any more. If the server is then restarted, you can invoke `M-x t-mouse-run' to restart mouse responsiveness in the editor.

The keymap is configured to handle the following events:

down-mouse-1
Jumps to the location of the click, setting the mark.
drag-mouse-1
Drags the emacs pointer to follow your mouse. The mouse cursor is displayed as well.
mouse-1
At mouse release, the cursor flashes to the mark (where the button was pressed), and point remains at the release location. The region remains set, though emacs doesn't allow highlighting while in text mode. If no drag happened, button release has no effect.
down-mouse-2
This event yanks the top item in the kill-ring, like the key-press of C-y.
down-mouse-3
Sets point. This can be used after a button-1 event to set the region without dragging.
double-mouse-1
Sets the region to a single word, or to all the words surrounding the region dragged on. The value of t-mouse-word-syntax is used to tell which syntax classes are considered to be part of a word (default ""w_"").
triple-mouse-1
Sets the region to a single line, or to all the lines surrounding the region dragged on.
double-mouse-3
Kills the region.
mode-line mouse-1
Selects the window.
mode-line drag-mouse-1
Changes the size of the current window to track the mouse.
mode-line mouse-2
Expands the window to the whole frame.
mode-line mouse-3
Deletes the window.
mode-line M-mouse-2
Splits the window horizontally.
mode-line M-mouse-3
Splits the window vertically
vertical-line drag-mouse-1
Changes the size of the current window to track the mouse.
vertical-line mouse-2
Splits the window horizontally
vertical-line mouse-3
Splits the window horizontally
scroll-bar down-mouse-1
Moves the line at the level where you click up to the top of the window. By clicking repeatedly in the same place, you can scroll by the same distance over and over.
M-down-mouse-1
Meta-mouse on the window acts in the same way as the scrollbar.
scroll-bar down-mouse-2
This does nothing (jumping has proven bad, due to lack of a visible scrollbar on screen).
scroll-bar drag-mouse-2
Dragging on the scroll-bar causes the buffer to scroll. The amount of scrolling is controlled by the X position of the mouse, in order to overcome the coarse granularity of the scroll-bar. In other words, horizonatal motion controls the vertical resolution, while vertical motion causes actual scrolling. The maximum vertical resolution is such that dragging from top to bottom of window can scan the whole buffer.
M-drag-mouse-2
Meta-mouse on the window acts in the same way as the scrollbar. This means taht you can use the low-resolution scrollbar without grabbing the bar on the right and then lowering the resolution.
scroll-bar down-mouse-3
Moves the line at the top of the window down to the level where you click. By clicking repeatedly in the same place, you can scroll by the same distance over and over.
M-down-mouse-3
Meta-mouse on the window acts in the same way as the scrollbar.

The "gpm-root" program

The program gpm-root is designed to handle Control-Mouse events to draw menus on the background of the current tty. The actual menus are described by a configuration file in the user's home directory.

Please note that gpm-root needs to run with Linux 1.1.73 or newwer, because previous kernels lack some screen handling capabilities required by the program.

The program uses the files /dev/vcs* to draw to the console screen. These are available only from kernel 1.1.81 onward. If you miss those device nodes, you should create them using create_vcs in the distribution directory. The tool won't run with kernels older than 1.1.81, because they lacked a full screen dump/restore capability.

Available command line options are the following:

-m number
Choose the modifier to use (by default: control). The modifier can be provided either as a number or as a symbolic string. Allowed strings are "shift", "anyAlt", "leftAlt", "rightAlt", "control".
-u
Deny using user-specific configuration files. With this option on, only /etc/gpm-root.conf will be used as a source of configuration information. This option is intended for those system administrators who fear security could be broken by this daemon. Thigs should be sufficiently secure, but if you find a hole please tell me about it.

Each time a menu is drawn, the configuration file is reparsed if it has changed. This allows modification of personal setup without reinvoking the daemon.

The actual configuration file is better introduced by an example:

# sample configuration file for gpm-root
# edit it to suit your taste

button 2 {
  name "system status"
  foreground red
  background black
  border yellow
  head bright yellow

  ""          f.nop
  "load: "    f.load
  "free:"     f.free
  "---------" f.nop
  "disk usage" f.bgcmd  "du | sort -rn > /tmp/du"
}

button 3 {
  name "jump"

  foreground black
  background red
  border bright yellow
  head bright yellow

  "tty1"  f.jptty  "1"
  "tty2"  f.jptty  "2"
  "tty3"  f.jptty  "3"
  "tty4"  f.jptty  "4"
  "tty5"  f.jptty  "5"
  "tty6"  f.jptty  "6"
    ""        f.nop
    "more of them..." {
          "tty 17" f.jptty  "17"
          }
 }

The syntax for the file won't be described here, being it quite apparent from the example above. Blanks and newlines are unused in parsing the file, and the layout of the file is free. Comments are allowed in the file: any hash mark (`#') found at the beginning of the line or after white space makes the parser discard anything up to the next line. To insert quotes (") in strings precede them with a backslash.

Note that recursive menus are allowed, to any level of recursion.

Keywords belong to three groups: the "button" keyword, the cfg keywords and the action keywords. They are all described in the table below:

button number menu
The "button" keyword is used to introduce a menu. It is followed by the number of the relevant button (1=left, 2=middle, 3=right), an open brace, a menu and a closed brace. A menu is made up of cfg statements, followed by action statements. Cfg statements can come in any order, while the order of action statements tells the actual order in which actions will appear on the screen, top to bottom.

The following statements belong to the cfg set.

name string
If the "name" keyword is present, the specified string will be used as the name for the current menu.
background color
This statements is used to specify the background color to be used in the current menu. The color can be specified with one of the eight canonical strings "black", "red", "cyan" etc. The background defaults to black.
foreground color
This statements is used to specify the foreground color for menu items. Its value defaults to "white". An optional "bright" keyword can appear before the actual color.
border color
"border" is used to specify the border color for the menu. Its value defaults to "white". An optional "bright" keyword can appear before the actual color.
head color
"head" is used to specify the foreground color for the title of the menu. Its value defaults to "white". An optional "bright" keyword can appear before the actual color.

The following statements belong to the `action' set.

string f.fgcmd cmdstring
When the mouse button is released above the corresponding menu item, the `cmdstring' is pasted in the keyboard queue of the current console. This is not yet implemented.
string f.bgcmd cmdstring
When the mouse button is released above the corresponding menu item, a shell (/bin/sh) is forked to execute the specified command, with stdin connected to `/dev/null', and stdout, stderr connected to the active console.
string f.jptty ttynumber
When the mouse button is released above the corresponding menu item, the console is switched to the one specified. The `ttynumber' must be specified as a string. Any tty can be reached this way, even those which are not accessible via the keyboard.
string f.mktty ttynumber
When the mouse button is released above the corresponding menu item, an unused console is selected, and /sbin/agetty is executed in it. The current console is switched to the newly opened console. I use this command to save kernel memory by opening a single console through `/etc/inittab' and requesting the others only when i need to login.
string { Whole-menu
A menu can directly follow the lable string. When the mouse pointer leaves the menu frame at the level of `string', a second menu is posted on screen.
string f.lock
When the mouse button is released above the corresponding menu item, the keyboard and the screen are locked, and only the locking user or the superuser can unlock them. This is not yet implemented.
string f.load
The current loadavg when the menu is posted is concatenated to `string' to build the actual message displayed on screen. Nothing happens at button release.
string f.free
The free memory and swap when the menu is posted is concatenated to `string' to build the actual message displayed on screen. Nothing happens at button release.
string f.time
The current time is formatted with strftime(3), according to `string'. The resulting string is the actual message displayed on screen. Nothing happens at button release.
string f.pipe cmdline
When the mouse pointer leaves the menu frame at the level of `string', a message box is posted on screen showing the last ten lines of the output of `cmdline'. The `cmdline' is executed by `/bin/sh'. This is not yet implemented.
string f.nop
This does nothing, it only displays `string' on the menu.

The HOME, LOGNAME and USER environment variables are setup to the values for the invoking user before spawning an external process (`f.bgcmd', `f.pipe'). The current directory is always /.

Known bugs have been fixed. In particular, if you invoke gpm-root right after gpm, it will delasy a few seconds before trying to connect to the daemon.

hltest

High-level test is a simple sample application using the high-level library. It implements something like a window manager for text windows, though it is small and unuseful.

The application is meant to be read by programmers trying to use the high-level library. It is equipped with event reporting to help in understanding the internal workings.

mouse-test

This experimental and incomplete application tries to help in detecting which protocol does your mouse speak. It is able to detect MouseMan devices, and to choose between "-t ms" (three-buttons aware) and "-t bare" old two-buttons-only serial mice.

I know the application is buggy, but I only own one mouse device. If you are interested in this application, just call me and awake me from my laziness.

API Index

Jump to: ( - * - g

(

  • (ePtr);
  • *

  • *Gpm_GetLibVersion
  • *Gpm_GetServerVersion
  • *Gpm_HandleRoi
  • *Gpm_LowerRoi
  • *Gpm_PopRoi
  • *Gpm_PushRoi
  • *Gpm_RaiseRoi
  • *Gpm_UseRoi
  • g

  • Gpm_Close, Gpm_Close
  • gpm_current_roi
  • gpm_data
  • Gpm_DrawPointer, Gpm_DrawPointer
  • GPM_DRAWPOINTER, GPM_DRAWPOINTER
  • Gpm_Event
  • gpm_fd
  • Gpm_FitEvent
  • Gpm_FitValues, Gpm_FitValues
  • Gpm_FitValuesM, Gpm_FitValuesM
  • gpm_flag
  • Gpm_Getc, Gpm_Getc
  • Gpm_Getch, Gpm_Getch
  • Gpm_Getchar, Gpm_Getchar
  • Gpm_GetEvent, Gpm_GetEvent
  • Gpm_GetLibVersion
  • Gpm_GetServerVersion
  • Gpm_GetSnapshot, Gpm_GetSnapshot
  • gpm_handler
  • Gpm_Handler
  • Gpm_HandleRoi
  • gpm_hflag
  • Gpm_LowerRoi
  • gpm_morekeys
  • gpm_mx
  • gpm_my
  • Gpm_Open, Gpm_Open
  • Gpm_PopRoi
  • Gpm_PushRoi
  • Gpm_RaiseRoi
  • Gpm_Repeat, Gpm_Repeat
  • gpm_roi
  • Gpm_roi
  • gpm_roi_data
  • gpm_roi_handler
  • gpm_tried
  • Gpm_UseRoi
  • gpm_visiblepointer
  • Gpm_Wgetch, Gpm_Wgetch
  • gpm_zerobased

  • This document was generated on 10 April 1999 using the texi2html translator version 1.52.