On using the mouse A brief introduction to LIBGPM: programming interface

advertisement
On using the mouse
A brief introduction to LIBGPM:
the General Purpose Mouse
programming interface
Diversity of hardware
• As with SVGA devices, there are computer
mice from a diversity of vendors – and no
universal standard hardware design
• The customary solution: a software layer is
created which ‘hides’ hardware differences
• For Linux platforms, the ‘libgpm’ package
provides one such software-layer – though
it was intended for text-based applications
Example: the PS/2 Mouse
The Mouse Report Format (3 bytes)
7
Byte 0
6
5
4
Y-data X-data
Y-data X-data
over
over
sign
sign
flow
flow
3
0
2
1
0
Middle Right Left
Button Button Button
down down down
Byte 1
X-coordinate data (bits 7..0)
Byte 2
Y-coordinate data (bits 7..0)
Other types of computer mice use different report formats
with possibly a different number of bytes (e.g., 4 or 5)
The Linux “gpm” package
•
•
•
•
•
•
•
It’s a mouse server for the Linux console
It “hides” details about mouse hardware
Intended for use with text-based programs
But we can use it with graphics programs
Requires that the gpm daemon is running
Type ‘info gpm’ to see official information
Also an online article by Pradeep Padala
Programming steps
• Your client application must establish a
connection with the gpm server-daemon
• You need a header-file: #include <gpm.h>
• You declare an important data-structure:
Gpm_Connect conn;
• You will need to initialize its four fields
• Then you call Gpm_Open( &conn, 0 );
• Returns -1 if unsuccessful (otherwise 0)
Fields to be initialized
conn.eventMask = ~0;
conn.defaultMask = 0;
conn.minMod = 0;
conn.maxMod = ~0;
// events of interest
// to handle for you
// lowest modifier
// highest modifer
Responding to mouse activity
• You create your own ‘handler’ function for those
mouse events that you wish to act upon
• Prototype of the handler-function is:
int my_handler( Gpm_Event *evt,
void *my_data );
• To install the handler, use this assignment:
gpm_handler = my_handler;
• Whenever the mouse is moved, or its buttons
are pressed or released, your function executes
Useful fields in Gpm_Event
Gpm_Event *evt;
evt->type == 1: // indicates a mouse-move
evt->x, evt->y: // current mouse ‘hot-spot’
evt->dx, evt->dy: // changes in position(+/-)
NOTE: Remember that GPM was developed
for text-based applications, so the hot-spot
coordinates are character-cell locations
(not graphics-pixel locations)
The GPM mouse-event mask
#include <gpm.h>
L
E
A
V
E
E
N
T
E
R
H
A
R
D
M
O
V
C
L
K
T
R
I
P
L
E
D
O
U
B
L
E
S
I
N
G
L
E
U
P
D
O
W
N
D
R
A
G
Your event-handler function will ‘test’ one or more of these flag-bits
to determine what type of state-change the mouse has undergone,
so that your application can respond to it in an appropriate manner
M
O
V
E
A typical program loop
This loop allows normal keyboard input to
continue being processed (e.g., echoed,
buffered) while any mouse activities are
processed by your handler (or else by a
default handler supplied by the daemon)
int
c;
while ( ( c = Gpm_Getc( stdin ) ) != EOF );
Gpm_Close();
A simple text-mode demo
• Pradeep Padala has published a short C
program that illustrates ‘barebones’ usage
of the gpm package (from Linux Journal)
• We have adapted his code for C++
• Our demo is called ‘trymouse.cpp’
• It’s compiled like this:
$ g++ trymouse.cpp –lgpm –o trymouse
A simple graphics demo
• We have created a minimal graphics demo
• It shows how you could use the mouse to
move a ‘slider’ object (e.g.,in Pong game)
• It’s called ‘gpmslide.cpp’
• You compile it like this:
$ g++ gpmslide.cpp –lgpm –o gpmslide
More elaborate graphics demo
• We also created a more elaborate mousedemo (called ‘seemouse.cpp’)
• It defines its own custom mouse-cursor
• It handles the four most common types of
mouse events:
– GPM_MOVE
– GPM_DOWN
– GPM_DRAG
– GPM_UP
Our mouse cursor
• We built a 2-color 16-by-16 pixel image
We used an array of
character-strings
to define our image
with only three
character-values
‘0’ = transparent color
‘1’ = background color
‘2’ = foreground color
Our mouse cache
• Each time we want to draw our cursor, we
first copy the existing 16-by-16 pixel-grid
that occupies the planned cursor-location
• Then we can draw our cursor threre
• When the mouse is moved, we need to
‘erase’ our cursor-image (by copying the
saved background there), and then saveand-draw our cursor in the new location
In-class exercise #1
• Can you create a different cursor-image,
based on your own design ideas? Will
your design define a different ‘hot-spot’?
Will you need to modify the boundaries to
keep your cursor from going out-of-view?
Demo: ‘persists.cpp’
• We created a sound-playing program that
plays a continuous tone – until a ‘signal’ is
received (asynchronous notification) that
the user has pressed the <ESCAPE> key
• We used an ‘ioctl’ command to ‘RESET’
the playback device – to stop the tone’s
sound almost immediately when our user
presses the <ESCAPE> key
In-class exercise #2
• Try commenting out the final ‘ioctl’() call in
our ‘persists.cpp’ demo, then recompile it
and execute that demo again. Does the
sound cease immediately?
• Can you incorporate the sound-effect into
our ‘seemouse.cpp’ demo, so that a user
can start the tone by pressing the mousebutton, and stop the tone by releasing it?
Download