📄 grx11.c
字号:
/************************************************************************/
/************************************************************************/
typedef struct grX11Surface_
{
grSurface root;
Display* display;
Window win;
Visual* visual;
Colormap colormap;
GC gc;
int depth;
XImage* ximage;
grBitmap ximage_bitmap;
const grX11Format* format;
grX11ConvertFunc convert;
int win_org_x, win_org_y;
int win_width, win_height;
int image_width, image_height;
char key_buffer[10];
int key_cursor;
int key_number;
} grX11Surface;
/* close a given window */
static void
gr_x11_surface_done( grX11Surface* surface )
{
Display* display = surface->display;
if ( display )
{
if ( surface->ximage )
{
XDestroyImage( surface->ximage );
surface->ximage = 0;
}
if ( surface->win )
{
XUnmapWindow( display, surface->win );
surface->win = 0;
}
}
}
static void
gr_x11_surface_refresh_rect( grX11Surface* surface,
int x,
int y,
int w,
int h )
{
grX11Blitter blit;
if ( !gr_x11_blitter_reset( &blit, &surface->root.bitmap,
&surface->ximage_bitmap,
x, y, w, h ) )
{
surface->convert( &blit );
XPutImage( surface->display,
surface->win,
surface->gc,
surface->ximage,
blit.x, blit.y, blit.x, blit.y, blit.width, blit.height );
}
}
static void
gr_x11_surface_refresh( grX11Surface* surface )
{
gr_x11_surface_refresh_rect( surface, 0, 0,
surface->root.bitmap.width,
surface->root.bitmap.rows );
}
static void
gr_x11_surface_set_title( grX11Surface* surface,
const char* title )
{
XStoreName( surface->display, surface->win, title );
}
static grKey
KeySymTogrKey( KeySym key )
{
grKey k;
int count = sizeof ( key_translators ) /
sizeof( key_translators[0] );
Translator* trans = key_translators;
Translator* limit = trans + count;
k = grKeyNone;
while ( trans < limit )
{
if ( trans->xkey == key )
{
k = trans->grkey;
break;
}
trans++;
}
return k;
}
static void
gr_x11_surface_listen_event( grX11Surface* surface,
int event_mask,
grEvent* grevent )
{
XEvent x_event;
KeySym key;
Display* display = surface->display;
int bool_exit;
grKey grkey;
XComposeStatus compose;
/* XXX: for now, ignore the event mask, and only exit when */
/* a key is pressed */
(void)event_mask;
bool_exit = surface->key_cursor < surface->key_number;
XDefineCursor( display, surface->win, x11dev.idle );
while ( !bool_exit )
{
XNextEvent( display, &x_event );
switch ( x_event.type )
{
case KeyPress:
surface->key_number = XLookupString( &x_event.xkey,
surface->key_buffer,
sizeof ( surface->key_buffer ),
&key,
&compose );
surface->key_cursor = 0;
if ( surface->key_number == 0 ||
key > 512 )
{
/* this may be a special key like F1, F2, etc. */
grkey = KeySymTogrKey( key );
if ( grkey != grKeyNone )
goto Set_Key;
}
else
bool_exit = 1;
break;
case MappingNotify:
XRefreshKeyboardMapping( &x_event.xmapping );
break;
case Expose:
#if 1
/* we don't need to convert the bits on each expose! */
XPutImage( surface->display,
surface->win,
surface->gc,
surface->ximage,
x_event.xexpose.x,
x_event.xexpose.y,
x_event.xexpose.x,
x_event.xexpose.y,
x_event.xexpose.width,
x_event.xexpose.height );
#else
gr_x11_surface_refresh_rectangle( surface,
x_event.xexpose.x,
x_event.xexpose.y,
x_event.xexpose.width,
x_event.xexpose.height );
#endif
break;
/* You should add more cases to handle mouse events, etc. */
}
}
XDefineCursor( display, surface->win, x11dev.busy );
XFlush ( display );
/* now, translate the keypress to a grKey; */
/* if this wasn't part of the simple translated keys, */
/* simply get the charcode from the character buffer */
grkey = grKEY( surface->key_buffer[surface->key_cursor++] );
Set_Key:
grevent->type = gr_key_down;
grevent->key = grkey;
}
static int
gr_x11_surface_init( grX11Surface* surface,
grBitmap* bitmap )
{
Display* display;
int screen;
grBitmap* pximage = &surface->ximage_bitmap;
const grX11Format* format;
surface->key_number = 0;
surface->key_cursor = 0;
surface->display = display = x11dev.display;
screen = DefaultScreen( display );
surface->depth = x11dev.format->x_depth;
surface->visual = x11dev.visual;
surface->format = format = x11dev.format;
surface->root.bitmap = *bitmap;
switch ( bitmap->mode )
{
case gr_pixel_mode_rgb24:
surface->convert = format->rgb_convert;
break;
case gr_pixel_mode_gray:
/* we only support 256-gray level 8-bit pixmaps */
if ( bitmap->grays == 256 )
{
surface->convert = format->gray_convert;
break;
}
default:
/* we don't support other modes */
return 0;
}
/* allocate surface image */
{
int bits, over;
bits = bitmap->width * format->x_bits_per_pixel;
over = bits % x11dev.scanline_pad;
if ( over )
bits += x11dev.scanline_pad - over;
pximage->pitch = bits >> 3;
pximage->width = bitmap->width;
pximage->rows = bitmap->rows;
}
pximage->buffer =
(unsigned char*)grAlloc( pximage->pitch * pximage->rows );
if ( !pximage->buffer )
return 0;
/* create the bitmap */
if ( grNewBitmap( bitmap->mode,
bitmap->grays,
bitmap->width,
bitmap->rows,
bitmap ) )
return 0;
surface->root.bitmap = *bitmap;
/* Now create the surface X11 image */
surface->ximage = XCreateImage( display,
surface->visual,
format->x_depth,
ZPixmap,
0,
(char*)pximage->buffer,
pximage->width,
pximage->rows,
x11dev.scanline_pad,
0 );
if ( !surface->ximage )
return 0;
{
XColor color, dummy;
XTextProperty xtp;
XSizeHints xsh;
XSetWindowAttributes xswa;
long xswa_mask = CWBackPixel | CWEventMask | CWCursor;
xswa.border_pixel = BlackPixel( display, screen);
if (surface->visual == DefaultVisual( display, screen ) )
{
xswa.background_pixel = WhitePixel( display, screen );
surface->colormap = DefaultColormap( display, screen );
}
else
{
xswa_mask |= CWColormap | CWBorderPixel;
xswa.colormap = XCreateColormap( display,
RootWindow( display, screen ),
surface->visual,
AllocNone );
XAllocNamedColor( display, xswa.colormap, "white", &color, &dummy );
xswa.background_pixel = color.pixel;
surface->colormap = xswa.colormap;
}
xswa.cursor = x11dev.busy;
xswa.event_mask = KeyPressMask | ExposureMask;
surface->win = XCreateWindow( display,
RootWindow( display, screen ),
0,
0,
bitmap->width,
bitmap->rows,
10,
format->x_depth,
InputOutput,
surface->visual,
xswa_mask,
&xswa );
XMapWindow( display, surface->win );
surface->gc = XCreateGC( display, surface->win,
0L, NULL );
XSetForeground( display, surface->gc, xswa.border_pixel );
XSetBackground( display, surface->gc, xswa.background_pixel );
/* make window manager happy :-) */
xtp.value = (unsigned char*)"FreeType";
xtp.encoding = 31;
xtp.format = 8;
xtp.nitems = strlen( (char*)xtp.value );
xsh.x = 0;
xsh.y = 0;
xsh.width = bitmap->width;
xsh.height = bitmap->rows;
xsh.flags = PPosition | PSize;
xsh.flags = 0;
XSetWMProperties( display, surface->win, &xtp, &xtp,
NULL, 0, &xsh, NULL, NULL );
}
surface->root.done = (grDoneSurfaceFunc)gr_x11_surface_done;
surface->root.refresh_rect = (grRefreshRectFunc)gr_x11_surface_refresh_rect;
surface->root.set_title = (grSetTitleFunc) gr_x11_surface_set_title;
surface->root.listen_event = (grListenEventFunc)gr_x11_surface_listen_event;
gr_x11_surface_refresh( surface );
return 1;
}
grDevice gr_x11_device =
{
sizeof( grX11Surface ),
"x11",
gr_x11_device_init,
gr_x11_device_done,
(grDeviceInitSurfaceFunc) gr_x11_surface_init,
0,
0
};
#ifdef TEST
typedef struct grKeyName
{
grKey key;
const char* name;
} grKeyName;
static const grKeyName key_names[] =
{
{ grKeyF1, "F1" },
{ grKeyF2, "F2" },
{ grKeyF3, "F3" },
{ grKeyF4, "F4" },
{ grKeyF5, "F5" },
{ grKeyF6, "F6" },
{ grKeyF7, "F7" },
{ grKeyF8, "F8" },
{ grKeyF9, "F9" },
{ grKeyF10, "F10" },
{ grKeyF11, "F11" },
{ grKeyF12, "F12" },
{ grKeyEsc, "Esc" },
{ grKeyHome, "Home" },
{ grKeyEnd, "End" },
{ grKeyPageUp, "Page_Up" },
{ grKeyPageDown, "Page_Down" },
{ grKeyLeft, "Left" },
{ grKeyRight, "Right" },
{ grKeyUp, "Up" },
{ grKeyDown, "Down" },
{ grKeyBackSpace, "BackSpace" },
{ grKeyReturn, "Return" }
};
#if 0
int
main( void )
{
grSurface* surface;
int n;
grInit();
surface = grNewScreenSurface( 0, gr_pixel_mode_gray, 320, 400, 128 );
if ( !surface )
Panic( "Could not create window\n" );
else
{
grColor color;
grEvent event;
const char* string;
int x;
grSetSurfaceRefresh( surface, 1 );
grSetTitle( surface, "X11 driver demonstration" );
for ( x = -10; x < 10; x++ )
{
for ( n = 0; n < 128; n++ )
{
color.value = ( n * 3 ) & 127;
grWriteCellChar( surface,
x + ( ( n % 60 ) << 3 ),
80 + ( x + 10 ) * 8 * 3 + ( ( n / 60 ) << 3 ),
n, color );
}
}
color.value = 64;
grWriteCellString( surface, 0, 0, "just an example", color );
do
{
listen_event( (grXSurface*)surface, 0, &event );
/* return if ESC was pressed */
if ( event.key == grKeyEsc )
return 0;
/* otherwise, display key string */
color.value = ( color.value + 8 ) & 127;
{
int count = sizeof ( key_names ) / sizeof ( key_names[0] );
grKeyName* name = key_names;
grKeyName* limit = name + count;
const char* kname = 0;
char kname_temp[16];
while ( name < limit )
{
if ( name->key == event.key )
{
kname = name->name;
break;
}
name++;
}
if ( !kname )
{
sprintf( kname_temp, "char '%c'", (char)event.key );
kname = kname_temp;
}
grWriteCellString( surface, 30, 30, kname, color );
grRefreshSurface( surface );
paint_rectangle( surface, 0, 0,
surface->bitmap.width, surface->bitmap.rows );
}
} while ( 1 );
}
return 0;
}
#endif /* O */
#endif /* TEST */
/* END */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -