?? xlib.c
字號:
/* * xlib.c * * Xlib interface. * dist under gnu gpl */#ifdef HAVE_CONFIG_H#include "config.h"#if defined(HAVE_LIBXEXT) && defined(HAVE_X11_EXTENSIONS_XSHM_H) \ && defined(HAVE_SYS_IPC_H) && defined(HAVE_SYS_SHM_H)#define USE_XSHM#endif#else#define USE_XSHM /* assume we have shm if no config.h */#endif#include <stdlib.h>#include <X11/Xlib.h>#include <X11/Xutil.h>#include <X11/keysym.h>#ifdef USE_XSHM#include <X11/extensions/XShm.h>#include <sys/ipc.h>#include <sys/shm.h>#endif#include "fb.h"#include "input.h"#include "rc.h"struct fb fb;static int vmode[3] = { 0, 0, 0 };static int x_shmsync = 1;rcvar_t vid_exports[] ={ RCV_VECTOR("vmode", &vmode, 3), RCV_BOOL("x_shmsync", &x_shmsync), RCV_END};static int initok;/* Loads of bogus Xlib crap...bleh */static char *x_displayname;static Display *x_display;static int x_screen;static struct{ int bits; int vc; int bytes;} x_vissup[] ={ { 8, PseudoColor, 1 }, { 15, TrueColor, 2 }, { 16, TrueColor, 2 }, { 32, TrueColor, 4 }, { 24, TrueColor, 3 }, { 0, 0, 0 }};static int x_bits, x_bytes;static Visual *x_vis;static XVisualInfo x_visinfo;static int x_pseudo;static Colormap x_cmap;static XColor x_ctable[256];static int x_wattrmask;static XSetWindowAttributes x_wattr;static int x_gcvalmask;static XGCValues x_gcval;static Window x_win;static int x_win_x, x_win_y;static int x_width, x_height;static GC x_gc;static XSizeHints x_size;static XWMHints x_wmhints;/*static XClassHint x_class;*/#ifdef USE_XSHMstatic XShmSegmentInfo x_shm;#endifstatic int x_useshm;static int x_shmevent;static int x_shmdone;static XImage *x_image;static int x_byteswap;static XEvent x_ev;static void freescreen(){ if (!initok || !x_image) return; if ((char *)fb.ptr != (char *)x_image->data) free(fb.ptr);#ifdef USE_XSHM if (x_useshm) { /* FIXME - is this the right way to free shared mem? */ XSync(x_display, False); if (!XShmDetach(x_display, &x_shm)) die ("XShmDetach failed\n"); XSync(x_display, False); shmdt(x_shm.shmaddr); shmctl(x_shm.shmid, IPC_RMID, 0); x_image->data = NULL; }#endif free(x_image); x_image = NULL; fb.ptr = NULL;}static void allocscreen(){ if (initok) freescreen();#ifdef USE_XSHM if (x_useshm) { x_image = XShmCreateImage( x_display, x_vis, x_bits, ZPixmap, 0, &x_shm, x_width, x_height); if (x_image) { x_shm.shmid = shmget( IPC_PRIVATE, x_image->bytes_per_line * x_image->height, IPC_CREAT | 0777); if (x_shm.shmid < 0) die("shmget failed\n"); x_image->data = x_shm.shmaddr = shmat(x_shm.shmid, 0, 0); if (!x_image->data) die("shmat failed\n"); if (!XShmAttach(x_display, &x_shm)) die("XShmAttach failed\n"); XSync(x_display, False); x_shmdone = 1; fb.pitch = x_image->bytes_per_line; } else { x_useshm = 0; } }#endif if (!x_useshm) { x_image = XCreateImage( x_display, x_vis, x_bits, ZPixmap, 0, malloc(x_width*x_height*x_bytes), x_width, x_height, x_bits, x_width*x_bytes); if (!x_image) die("XCreateImage failed\n"); } x_byteswap = x_image->byte_order ==#ifdef IS_LITTLE_ENDIAN MSBFirst#else LSBFirst#endif ; if (x_byteswap && x_bytes > 1) fb.ptr = malloc(x_image->bytes_per_line * x_image->height); else fb.ptr = x_image->data;}void vid_resize(){ freescreen(); x_width = fb.w; x_height = fb.h; XResizeWindow(x_display, x_win, x_width, x_height); x_size.flags = PSize | PMinSize | PMaxSize; x_size.min_width = x_size.max_width = x_size.base_width = x_width; x_size.min_height = x_size.max_height = x_size.base_height = x_height; XSetWMNormalHints(x_display, x_win, &x_size); XSync(x_display, False); allocscreen();}static void colorshifts(){ int i; int mask[3]; int l, c; mask[0] = x_vis->red_mask; mask[1] = x_vis->green_mask; mask[2] = x_vis->blue_mask; for (i = 0; i < 3; i++) { for (l = 0; l < 32 && !((1<<l) & mask[i]); l++); for (c = 0; l+c < 32 && ((1<<(l+c)) & mask[i]); c++); fb.cc[i].l = l; fb.cc[i].r = 8-c; }}void vid_preinit(){ /* do nothing; only needed on systems where we must drop perms */}void vid_init(){ int i; if (initok) return; x_displayname = getenv("DISPLAY"); if (!x_displayname) die("DISPLAY environment variable not set\n"); x_display = XOpenDisplay(NULL); if (!x_display) die("failed to connect to X display\n"); x_screen = DefaultScreen(x_display); for (i = 0; x_vissup[i].bits; i++) { if (XMatchVisualInfo( x_display, x_screen, x_vissup[i].bits, x_vissup[i].vc, &x_visinfo)) { if (x_vissup[i].vc == PseudoColor) x_pseudo = 1; else x_pseudo = 0; x_bits = x_vissup[i].bits; x_bytes = x_vissup[i].bytes; break; } } if (!x_bits) die("no suitable X visuals\n"); x_vis = x_visinfo.visual; if (!x_vis) die("X visual is NULL"); if (x_pseudo) { x_cmap = XCreateColormap( x_display, RootWindow(x_display, x_screen), x_vis, AllocAll); for (i = 0; i < 256; i++) { x_ctable[i].pixel = i; x_ctable[i].flags = DoRed|DoGreen|DoBlue; } } x_wattrmask = CWEventMask | CWBorderPixel | CWColormap; x_wattr.event_mask = KeyPressMask | KeyReleaseMask | ExposureMask | FocusChangeMask; x_wattr.border_pixel = 0; x_wattr.colormap = x_cmap; x_gcvalmask = GCGraphicsExposures; x_gcval.graphics_exposures = False; if (!vmode[0] || !vmode[1]) { int scale = rc_getint("scale"); if (scale < 1) scale = 1; vmode[0] = 160 * scale; vmode[1] = 144 * scale; } fb.w = vmode[0]; fb.h = vmode[1]; fb.pelsize = x_bytes == 3 ? 4 : x_bytes; fb.pitch = fb.w * fb.pelsize; fb.indexed = x_pseudo; fb.enabled = 1; fb.dirty = 0; x_win_x = x_win_y = 0; x_width = fb.w; x_height = fb.h; x_win = XCreateWindow( x_display, RootWindow(x_display, x_screen), x_win_x, x_win_y, x_width, x_height, 0, x_bits, InputOutput, x_vis, x_wattrmask, &x_wattr); if (!x_win) die("could not create X window\n"); x_gc = XCreateGC(x_display, x_win, x_gcvalmask, &x_gcval); x_size.flags = PSize | PMinSize | PMaxSize; x_size.min_width = x_size.max_width = x_size.base_width = x_width; x_size.min_height = x_size.max_height = x_size.base_height = x_height; XSetWMNormalHints(x_display, x_win, &x_size); x_wmhints.initial_state = NormalState; x_wmhints.input = True; x_wmhints.flags = StateHint | InputHint; XSetWMHints(x_display, x_win, &x_wmhints); /* FIXME - set X class info stuff (with XSetClassHint)... */ XMapWindow(x_display, x_win); for(;;) { XNextEvent(x_display, &x_ev); if (x_ev.type == Expose && !x_ev.xexpose.count) break; } XSetInputFocus(x_display, x_win, RevertToPointerRoot, CurrentTime);#ifdef USE_XSHM if (XShmQueryExtension(x_display) && x_displayname[0] == ':') { x_useshm = 1; x_shmevent = XShmGetEventBase(x_display) + ShmCompletion; }#endif colorshifts(); allocscreen(); joy_init(); initok = 1;}void vid_close(){ joy_close(); if (!initok) return; freescreen(); XFreeGC(x_display, x_gc); XDestroyWindow(x_display, x_win); XCloseDisplay(x_display); initok = 0;}/* keymap - mappings of the form { keysym, localcode } - from x11/keymap.c */extern int keymap[][2];static int mapxkeycode(int xkeycode){ int i; int sym; int code; sym = XKeycodeToKeysym(x_display, xkeycode, 0); for (i = 0; keymap[i][0]; i++) if (keymap[i][0] == sym) return keymap[i][1]; if (sym < XK_space || sym > XK_asciitilde) return 0; code = sym - XK_space + ' '; if (code >= 'A' && code <= 'Z') code = tolower(code);; return code;}void vid_end();static int nextevent(int sync){ event_t ev; if (!sync && !XPending(x_display)) return 0; XNextEvent(x_display, &x_ev); switch(x_ev.type) { case KeyPress: ev.type = EV_PRESS; ev.code = mapxkeycode(x_ev.xkey.keycode); break; case KeyRelease: ev.type = EV_RELEASE; ev.code = mapxkeycode(x_ev.xkey.keycode); break; case Expose: vid_end(); return 1; break; default: if (x_ev.type == x_shmevent) x_shmdone = 1; return 1; break; } return ev_postevent(&ev); /* returns 0 if queue is full */}void ev_poll(){ while (nextevent(0)); joy_poll();}void vid_settitle(char *title){ XStoreName(x_display, x_win, title); XSetIconName(x_display, x_win, title);}void vid_setpal(int i, int r, int g, int b){ if (!initok) return; if (x_pseudo == 1) { x_ctable[i].red = r << 8; x_ctable[i].green = g << 8; x_ctable[i].blue = b << 8; XStoreColors(x_display, x_cmap, x_ctable, 256); }}void vid_begin(){ if (!x_useshm) return; /* XSync(x_display, False); */ while (!x_shmdone && x_shmsync) nextevent(1);}static void endianswap(){ int cnt; un16 t16; un32 t32; un16 *src16 = (void *)fb.ptr; un16 *dst16 = (void *)x_image->data; un32 *src32 = (void *)fb.ptr; un32 *dst32 = (void *)x_image->data; switch (x_bytes) { case 2: cnt = (x_image->bytes_per_line * x_image->height)>>1; while (cnt--) { t16 = *(src16++); *(dst16++) = (t16 << 8) | (t16 >> 8); } break; case 4: cnt = (x_image->bytes_per_line * x_image->height)>>2; while (cnt--) { t32 = *(src32++); *(dst32++) = (t32 << 24) | ((t32 << 8) & 0x00FF0000) | ((t32 >> 8) & 0x0000FF00) | (t32 >> 24); } break; }}void vid_end(){ if (!initok) return; if (x_byteswap) endianswap(); if (x_useshm) { if (!x_shmdone) return;#ifdef USE_XSHM if (!XShmPutImage( x_display, x_win, x_gc, x_image, 0, 0, 0, 0, x_width, x_height, True)) die("XShmPutImage failed\n");#endif x_shmdone = 0; } else { XPutImage(x_display, x_win, x_gc, x_image, 0, 0, 0, 0, x_width, x_height); }}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -