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 Midnight 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 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. See gpm-root.
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-?.??.tar.gz from the mirrors of ftp://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.
As of release 1.20.0 the default device is removed. Now -m is a must.
Release 1.20.1 introduces the must for -t and a specific way to use -m,-t,-o: Now you've got to use -m first, then -t and at last -o. This seems to be more complex, but makes using of multiply mice possible with clean code.
Just say ./configure && make && make install
to your
shell. You'll need gpm installed to compile the latest release of
The Midnight Commander with mouse support enabled.
Binaries are not released with the package because it's safer for you to compile the package by yourself.
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 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. From release 1.02 up to 1.19.2 is was possible for any user logged on the system console to change the mouse feeling using the -q option. This is no longer possible for security reasons.
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.
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:
/sbin/shutdown -h now
/sbin/shutdown -r now
The `-S' command line 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.
Available command line options are the following:
-a
accel-A[
limit]
rm -rf /
) including the terminating line break, then all the
victim has to do is click the middle mouse button ..
As of version 1.17.2, this has developed
into a more general aging mechanism; the
gpm daemon can disable (age) selection pasting
automatically after a period of inactivity. To enable this mode
just give the optional limit parameter (no space in between !)
which is interpreted as the time in seconds for which a selection is
considered valid and pastable.
As of version 1.15.7, a trivial program called
disable-paste
is provided. The following makes a good
addition to /etc/profile if you allow multiple users to
work on your console.
case $( /usr/bin/tty ) in
/dev/tty[0-9]*) /usr/bin/disable-paste ;;
esac
-b
baud-B
sequence-d
delta-D
-g
number-h
-i
interval-k
-l
charsetinword()
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-M
-o
list-of-extra-options-p
-r
number-R[
name]
gpm
to act as a repeater: any mouse data received while
in graphic mode will be produced on the fifo /dev/gpmdata
in protocol name, given as an optional argument (no space in
between !). In principle, you can use the same
names as for the `-t' option, although repeating into some
protocols may not be implemented for a while. See Mouse Types.
In addition, you can specify `raw' as the name, to repeat
the mouse data byte by byte, without any protocol translation.
If name is omitted, it defaults to `msc'.
Using gpm in repeater mode, you can configure the X
server to use its 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-S
commands-t
name-v
-V[
verbosity increment]
LOG_NOTICE
).
See Program Arguments.
-2
-3
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 starting 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.
The clients shipped out with gpm are not updated, thus there are potential security risks when using them.
This section of the gpm documentation manual describes the various pointer types currently available in gpm. If you look at the source code, you'll find that pointer-specific code is confined to mice.c (while it used to only include mouse decoders, gpm now supports tablets and touchscreens as well).
The mouse type is specified on command line with the `-t' option. The option takes an argument, which represents the name of a mouse type. Each type can be associated to different names. For old mouse types, one name is the old selection-compatible name, and another is the XFree name. After version 1.18.1 of gpm, the number of synonyms was made arbitrary and the actual name being used is made available to the function responsible for mouse initialization. Therefore it is possible for a mouse decoder to behave slightly differently according to the name being used for the device (if this feature was already present, we wouldn't have for example ms+ and ms+lr as different mouse types).
The initialization procedure of each mouse type can also receive extra option, by means of the -o command line option. Since interpretation of the option string is decoder-specific, the allowed options are described in association to each mouse type. When no description of option strings is provided, that means the option string is unused for that mouse type and specifying one generates an error. When the document refer to “standard serial options” it means that one of -o dtr, -o rts, -o both can be specified to toggle the control lines of the serial port.
The following mouse type are corrently recognized:
bare Microsoft
gpm -t msc
while
keeping the middle button pressed. Very annoying, indeed.
This mouse decoder accepts standard serial options, although they
should not be needed.
ms
ms+
ms+lr
msc MouseSystems
mman Mouseman
sun
mm MMSeries
logi Logitech
bm BusMouse
ps2 PS/2
ncr
wacom
genitizer
logim
pnp
ms3
imps2
netmouse
cal
calr
twid
gpm
will anyway
repeat mouse events to the X server. More information about twiddler
support can be found in README.twiddler, in the gpm
distribution.
syn synaptics
synps2 synaptics_ps2
brw
js Joystick
summa
mtouch
gunze
acecad
wp wizardpad
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 selection 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).
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 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;
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;
shift_state
, as of keyboard.c, when the event is
reported. It is a bitmask value, and corresponds 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;
short x, y;
selection
and libcurses
. This behavior can be
overriden, though, by setting the library variable
gpm_zerobased
.
See Variables.
short dx, dy;
enum Gpm_Etype type;
int clicks;
enum Gpm_Margin margin;
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 Margins.
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 Utility Functions.
The type
field in 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
GPM_DRAG
GPM_DOWN
buttons
field will report
which buttons are pressed after the event.
GPM_UP
buttons
field will report
which buttons are being released. Note that this is different from
the previous case.
GPM_ENTER
GPM_ENTER
, all the other fields are undefined.
See High Level Lib.
GPM_LEAVE
GPM_LEAVE
have all other fields undefined.
Cooked events are the following:
GPM_SINGLE
GPM_DOUBLE
GPM_TRIPLE
GPM_MFLAG
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. See 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 Open and Close.
eventMask
defaultMask
minMod
maxMod
maxMod
won't
be passed to the client.
Gpm_Open
will do it for you.
int pid
int vc
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. They are detailed in Default Handlers, but you only need to choose the right values for your application.
Examples:
minMod=0; maxMod=0;
minMod=0; maxMod=~0;
minMod=1<<KG_SHIFT; maxMod=1<<KG_SHIFT;
minMod=1<<KG_SHIFT; maxMod=~0;
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
~eventMask
~GPM_HARD
eventMask
.
GPM_MOVE|GPM_HARD
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, in the order of decreasing priority:
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 configuration files in order to draw
menus on the background of your screen.
See gpm-root.
The libgpm.a archive is meant to provide the mouse protocol at
different levels of abstraction. 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).
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 typically 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
variable 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
Gpm_Getc
to return the same value to the caller, after setting
gpm_hflag
to 1.
0
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.
gpm_hflag
. This allows a quick way to implement yes/no
boxes and 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.
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 Xterm.
This is the list of all the global variables present in the client library:
int gpm_flag
int gpm_tried
int gpm_fd
int gpm_zerobased
int gpm_visiblepointer
gpm_mx
gpm_my
Gpm_Open
, and
updated by a SIGWINCH
handler internal to the library.
(Don't worry, the library doesn't replace any
SIGWINCH
handler your program may already have installed;
instead the library hooks the signal, that is, it calls
any preexisting handler after taking care of its own needs.)
int gpm_hflag
Gpm_Handler *gpm_handler; void *gpm_data
NULL
,
they're used to setup asynchronous mouse handling, as
described below under the Gpm_Getc()
item.
gpm_morekeys
gpm_morekeys
is not zero, Gpm_Getc
will
invoke the handler without waiting for events. gpm_morekeys
is never set by the mouse library.
Open a connection with the server. The conn parameter points to the connection information for the being-created connection, as already described. See Connection Details. It is passed to the server after filling the
pid
andvc
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 Default Handlers, while a positive value is used to force connection to a particular console, either for debugging issues or wheneverstdin
is not a tty whenGpm_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 witheventMask
zeroed, anddefaultMask
,minMod
andmaxMod
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 value forGpm_Open()
will be `-2'. This value is always available ingpm_fd
.
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.
Reads an event form
gpm_fd
. It should be called only when thegpm_fd
descriptor is reported as readable by aselect()
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.
It returns the number of characters (contained in
nbprevchar
index) queued into the arrayprevchar
by functionGpm_Getc
. This call is useful i.e. in recognition of function or arrow keys, when we need to know the next character read byGpm_getc
in order to subsequently get it.
It returns the number of characters (contained in
nbprevchar
index) queued into the arrayprevchar
by functionGpm_Getc
. This call is useful i.e. in recognition of function or arrow keys, when we need to know the next character read byGpm_getc
in order to subsequently get it.
These are intended to be replacements for
getc()
andgetchar()
to be used by applications which are interested in the mouse. Their external behaviour is the same asgetc()
, but a mouse handler gets invoked whenever an event is available. See Handling Functions. A mouse handler can forceGpm_Getc
to return a specific value to the caller, and the “simulated” character is signaled by settinggpm_hflag
to 1.
These are intended to be replacements for
wgetch()
andgetch()
to be used by applications which are interested in the mouse. They are the curses equivalent ofGpm_Getchar
.
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))...
).
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.
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
andgpm_my
. See Variables.
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.
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 returnNULL
)if nogpm
program is in the current path. Alternatively, it could fail (and return a wrong value) if thegpm
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 forGpm_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.
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.
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 low-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 only runs under xterm, please see gpm-xterm in the sample subdirectory of the distribution, which 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 hltest.
The high-level library is completely independent of the low-level one,
so it uses 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
described by a Gpm_Roi
structure, which is made up by the following
fields:
short xMin, xMax
short yMin, yMax
unsigned short minMod, maxMod
unsigned short eventMask
unsigned short owned
free(0
when
needed.
Gpm_Handler *handler
void *clientdata
Gpm_Roi *next, *prev
Gpm_Roi* gpm_roi
Gpm_Roi* gpm_current_roi
Gpm_Handler* gpm_roi_handler
void* gpm_roi_data
gpm_roi_handler
.
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. Thextradata
field will be used to fill thextradata
field inGpm_Roi
. the return value is the Roi just pushed (i.e. the top of stack).
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.
Used to extract a Region of Interest from the stack, this function will also clear the Region if it is needed.
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.
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.
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 relevant 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 alsoGPM_ENTER
andGPM_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.
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 sample/gpm-xterm.c is available to mimic 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.
mev
The mev
program is modeled after xev
. It prints to stdout
the
mouse console events it gets.
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 Emacs Support.
Command line switches for mev
are the following:
-C
number-d
number-e
number-E
-f
-i
stdin
to change connection
parameters.
-m
numbermev
. It defaults to `0'.
The mask must be provided either as a
decimal number, or as a symbolic string.
-M
numbermev
.
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
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' and `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.
Other commands recognized are `info', used to return the stack depth; `quit' to prematurely terminate the program; and `snapshot' to get some configuration information from the server.
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 Xterm.
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 correct site-lisp directory for you emacs installation (as detected by the configure phase).
Events with modifiers other than Meta, Control, and Shift are not managed by the library. Managed 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 gpm-root.
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 appended to the list variable
unread-command-events
where the Emacs main event loop will find
them. They can be made to trigger any command (or interactive function,
in Emacs Lisp terminology) at all. Actually Emacs already comes with
reasonable bindings for most mouse events, so usually you won't have to
do anything beyond installing t-mouse
. If you want to modify
what Emacs does in response to mouse events, please see
Keymaps.
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, again it can be turned off by changing the appropriate Emacs keymap.
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 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 the configuration file, /etc/gpm-root.conf.
The program uses the files /dev/vcs* to draw to the console screen.
Available command line options are the following:
-m
number-D
-V
verbosity incrementEach 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 menubutton
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
stringname
keyword is present, the specified
string will be used as the name for the current menu.
background
colorforeground
colorborder
colorborder
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
colorhead
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.
f.fgcmd
cmdstring f.bgcmd
cmdstringstdin
connected to /dev/null, and stdout
, stderr
connected
to the active console.
f.jptty
ttynumber f.mktty
ttynumber f.lock
f.load
f.free
f.time
f.pipe
cmdline f.nop
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 /.
Anyone with access to the console may cause gpm-root
to run any of
the commands given in /etc/gpm-root.conf as root.
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.
Gpm_CharsQueued
: Getting EventsGpm_Close
: Open and CloseGPM_DRAWPOINTER
: Utility FunctionsGpm_DrawPointer
: Utility FunctionsGpm_FitEvent
: Utility FunctionsGpm_FitValues
: Utility FunctionsGpm_FitValuesM
: Utility FunctionsGpm_Getc
: Getting EventsGpm_Getch
: Getting EventsGpm_Getchar
: Getting EventsGpm_GetEvent
: Getting EventsGpm_GetLibVersion
: Extra FunctionsGpm_GetServerVersion
: Extra FunctionsGpm_GetSnapshot
: Extra FunctionsGpm_HandleRoi
: hl-FunctionsGpm_LowerRoi
: hl-FunctionsGpm_Open
: Open and CloseGpm_PopRoi
: hl-FunctionsGpm_PushRoi
: hl-FunctionsGpm_RaiseRoi
: hl-FunctionsGpm_Repeat
: Utility FunctionsGpm_UseRoi
: hl-FunctionsGpm_Wgetch
: Getting Eventsgpm_current_roi
: hl-Variablesgpm_data
: Variablesgpm_fd
: Variablesgpm_flag
: Variablesgpm_handler
: Variablesgpm_hflag
: Variablesgpm_morekeys
: Variablesgpm_mx
: Variablesgpm_my
: Variablesgpm_roi
: hl-Variablesgpm_roi_data
: hl-Variablesgpm_roi_handler
: hl-Variablesgpm_tried
: Variablesgpm_visiblepointer
: Variablesgpm_zerobased
: Variables