//------------------------------------------------------------------- // gpmslide.cpp // // This program shows the essential steps in utilizing Linux's // 'General Purpose Mouse' programming-interface ('libgpm') in // a simple graphics application: the user can move a 'slider' // object back and forth, toward the left or toward the right. // // compile: $ g++ gpmslide.cpp int86.cpp -lgpm -o gpmslide // // programmer: ALLAN CRUSE // written on: 21 AUG 2003 // revised on: 21 SEP 2005 -- replaces svgalib with 'int86()' //------------------------------------------------------------------- #include // for open() #include // for lseek() #include // for tcgetattr(), tcsetattr() #include // for mmap() #include // for Gpm_Open() #include "int86.h" // for init8086(), int86() int vesa_mode = 0x4101, hres = 640, vres = 480; unsigned char *vram = (unsigned char*)0xA0000000; struct vm86plus_struct vm; // global variables (for control of the 'slider' object) int minx = 100, maxx = 340, locy = 236; int wide = 200, high = 8, bgcolor = 0; int curr = 220, prev = 220, fgcolor = 10; void fill_rectangle( int x, int y, int h, int v, int color ) { int minx = x, maxx = x+h, miny = y, maxy = y+v; for (y = miny; y < maxy; y++) for (x = minx; x < maxx; x++) vram[ y*hres + x ] = color; } int my_mouse_handler( Gpm_Event *evt, void *data ) { // for now we just ignore all mouse-events except 'moves' if ( evt->type != GPM_MOVE ) return 0; prev = curr; // save slider's current position curr += 2*evt->dx; // compute slider's next location // but make sure the slider won't be moving 'out-of-sight' if ( curr < minx ) curr = minx; // if too far leftward if ( curr > maxx ) curr = maxx; // if too far rightward if ( curr != prev ) // does the slider position change? { // yes, erase it and then redraw it fill_rectangle( prev, locy, wide, high, bgcolor ); fill_rectangle( curr, locy, wide, high, fgcolor ); } return 0; } void draw_rectangle( int x, int y, int h, int v, int color ) { int minx = 0, miny = 0, maxx = hres-1, maxy = vres-1; do { vram[ y*hres + x ] = color; ++x; } while ( x < maxx ); do { vram[ y*hres + x ] = color; ++y; } while ( y < maxy ); do { vram[ y*hres + x ] = color; --x; } while ( x > minx ); do { vram[ y*hres + x ] = color; --y; } while ( y > miny ); } int main( void ) { // memory-map the frame-buffer into user address-apace int fd = open( "/dev/vram", O_RDWR ); if ( fd < 0 ) { perror( "/dev/vram" ); return -1; } int size = lseek( fd, 0, SEEK_END ); int prot = PROT_READ | PROT_WRITE; int flag = MAP_FIXED | MAP_SHARED; if ( mmap( (void*)vram, size, prot, flag, fd, 0 ) == MAP_FAILED ) { perror( "mmap" ); return -1; } // enable non-canonical keyboard input struct termios otty; tcgetattr( 0, &otty ); struct termios tty = otty; tty.c_lflag &= ~( ICANON | ECHO | ISIG ); tty.c_cc[ VMIN ] = 1; tty.c_cc[ VTIME ] = 0; tcsetattr( 0, TCSAFLUSH, &tty ); // enter graphics mode init8086(); vm.regs.eax = 0x4F02; vm.regs.ebx = vesa_mode; int86( 0x10, vm ); // draw a screen border and initial image of the 'slider' int bordercolor = 15; draw_rectangle( 0, 0, hres, vres, bordercolor ); fill_rectangle( curr, locy, wide, high, fgcolor ); // establish our connection with the GPM daemon-process Gpm_Connect conn; conn.eventMask = ~0; conn.defaultMask = 0; conn.minMod = 0; conn.maxMod = ~0; if ( Gpm_Open( &conn, 0 ) != -1 ) { gpm_handler = my_mouse_handler; while ( Gpm_Getc( stdin ) != '\e' ); Gpm_Close(); } // leave graphics mode vm.regs.eax = 0x0003; int86( 0x10, vm ); // restore canonical keyboard-input tcsetattr( 0, TCSAFLUSH, &otty ); }