Found at: http://publish.ez.no/article/articleprint/95 |
Xlib tutorial 2 - Events and errors |
Welcome back to the second Xlib tutorial. This time we will make our little program behave much more like a real application. We will learn how to handle events from the X server in order to process user input and resizing of our window. We will also set the title property of the window and how to handle errors.
|
| The famous quit button |
int errorHandler( Display *dpy, XErrorEvent *e )
{
char errorText[1024];
XGetErrorText( dpy, e->error_code, errorText, sizeof(errorText) );
printf( "**********************************\n" );
printf( "X Error: %s\n", errorText );
printf( "**********************************\n" );
exit( 1 );
}
|
enum buttonState { NORMAL, HOVER, PRESSED };
void paintButton( Display *dpy, Painter *p, Window button, buttonState state = NORMAL )
{
XWindowAttributes attr;
// fetch window size
XGetWindowAttributes( dpy, button, &attr );
if( state == NORMAL )
p->setForeground( "gray" );
else
p->setForeground( "darkgray" );
p->drawRectangle( button, 0, 0, attr.width, attr.height, true );
p->setForeground( "red" );
p->drawRectangle( button, 0, 0, attr.width -1, attr.height -1, false );
// draw the button text
const char *text = "Quit";
// fetch the Font from the painter
const FFont *font = p->font();
// fetch the height of the font, and the width of the text.
int fontHeight = font->fontHeight(); // max height above and below baseline
int textWidth = font->textWidth( text );
// center the text at the top of the window
p->setForeground( "black" );
if( state == PRESSED )
p->drawText( button, 2 + (attr.width - textWidth)/2, 2 + (attr.height + fontHeight)/2, text );
else
p->drawText( button, (attr.width - textWidth)/2, (attr.height + fontHeight)/2, text );
}
|
void resize( Display *dpy, int mainW, int mainH, Window button )
{
XWindowAttributes attr;
// fetch button size
XGetWindowAttributes( dpy, button, &attr );
int buttonW = attr.width, buttonH = attr.height;
// place button in middle
XMoveWindow( dpy, button, (mainW - buttonW) /2, (mainH - buttonH)/2 );
}
|
XSelectInput( dpy, win, StructureNotifyMask | ExposureMask );
XSelectInput( dpy, button, ButtonPressMask | ButtonReleaseMask
| ExposureMask | EnterWindowMask | LeaveWindowMask );
|
XEvent event;
bool running = true;
bool buttonHover = false;
while( running )
{
XNextEvent( dpy, &event );
switch( event.type )
{
// the event handling code comes here.
}
}
|
case Expose:
{
paintButton( dpy, painter, button );
}
break;
|
case ConfigureNotify:
{
resize( dpy, event.xconfigure.width, event.xconfigure.height, button );
}
|
case ButtonPress:
{
paintButton( dpy, painter, button, PRESSED );
}
break;
|
case EnterNotify:
case LeaveNotify:
{
buttonHover = (event.type == EnterNotify ) ? true : false;
paintButton( dpy, painter, button, buttonHover ? HOVER : NORMAL );
}
break;
|
case ButtonRelease:
{
if( event.xbutton.window == button && buttonHover )
{
paintButton( dpy, painter, button, HOVER );
XFlush( dpy );
running = false;
}
}
|
char *title = "Hello!";
XTextProperty windowProp;
if( XStringListToTextProperty( &title, 1, &windowProp ) == 0 )
{
printf( "XStringListToTextProperty ran out of memory" );
exit( 1 );
}
XSetWMName( dpy, win, &windowProp );
XFree( windowProp.value );
|
Attached files: