X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=gph-gfx;a=blobdiff_plain;f=test_x11.c;fp=test_x11.c;h=1c9e1434d6fbf7856b6b41b62ebacbf9aa2795a6;hp=0000000000000000000000000000000000000000;hb=5ea3ab5302b95500424d61eab0dda97e98cc53d8;hpb=066a1766c12fd42bf2191842f1857c2a320942dd diff --git a/test_x11.c b/test_x11.c new file mode 100644 index 0000000..1c9e143 --- /dev/null +++ b/test_x11.c @@ -0,0 +1,220 @@ +#include +#include +#include +#include +#include +#include "gphgfx.h" + +static void redraw(void); +static void reshape(int x, int y); +static void keydown(int key, int x, int y); +static void keyup(int key, int x, int y); +static void button(int bn, int st, int x, int y); +static void motion(int x, int y); + +static int create_window(const char *title, int width, int height); +static void handle_event(XEvent *ev); +static KeySym translate_keysym(KeySym sym); +static void set_window_title(const char *title); + +static Display *dpy; +static int scr; +static Window win, root; +static Atom xa_wm_proto, xa_wm_del_win; +static int quit, mapped, win_width, win_height, modstate; +static GC gc; + +int main(int argc, char **argv) +{ + if(!(dpy = XOpenDisplay(0))) { + fprintf(stderr, "failed to connect to the X server\n"); + return 1; + } + xa_wm_proto = XInternAtom(dpy, "WM_PROTOCOLS", False); + xa_wm_del_win = XInternAtom(dpy, "WM_DELETE_WINDOW", False); + + scr = DefaultScreen(dpy); + root = RootWindow(dpy, scr); + + if(create_window("gph-gfx test", 800, 600) == -1) { + return 1; + } + + if(ggfx_init("test", GGFX_INIT_DEBUG) == -1) { + return 1; + } + + for(;;) { + while(XPending(dpy)) { + XEvent ev; + XNextEvent(dpy, &ev); + handle_event(&ev); + if(quit) goto end; + } + redraw(); + } +end: + + ggfx_shutdown(); + XFreeGC(dpy, gc); + XCloseDisplay(dpy); + return 0; +} + + +static void redraw(void) +{ + XSetForeground(dpy, gc, 0xff00); + XClearWindow(dpy, win); + usleep(10000); +} + +static void reshape(int x, int y) +{ + printf("reshape %dx%d\n", x, y); +} + +static void keydown(int key, int x, int y) +{ + switch(key) { + case 27: + quit = 1; + break; + } +} + +static void keyup(int key, int x, int y) +{ +} + +static void button(int bn, int st, int x, int y) +{ +} + +static void motion(int x, int y) +{ +} + +static int create_window(const char *title, int width, int height) +{ + XSetWindowAttributes xattr = {0}; + XVisualInfo vinf; + unsigned int xattr_mask; + + if(!XMatchVisualInfo(dpy, scr, 24, TrueColor, &vinf)) { + fprintf(stderr, "failed to find appropriate visual\n"); + return -1; + } + + xattr.background_pixel = BlackPixel(dpy, scr); + xattr.colormap = XCreateColormap(dpy, root, vinf.visual, AllocNone); + xattr_mask = CWBackPixel | CWColormap | CWBackPixmap | CWBorderPixel; + if(!(win = XCreateWindow(dpy, root, 0, 0, width, height, 0, vinf.depth, + InputOutput, vinf.visual, xattr_mask, &xattr))) { + fprintf(stderr, "Failed to create window\n"); + return -1; + } + + XSelectInput(dpy, win, ExposureMask | StructureNotifyMask | KeyPressMask | + KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask); + + set_window_title(title); + XSetWMProtocols(dpy, win, &xa_wm_del_win, 1); + XMapWindow(dpy, win); + + gc = XCreateGC(dpy, win, 0, 0); + return 0; +} + + +static KeySym translate_keysym(KeySym sym) +{ + switch(sym) { + case XK_Escape: + return 27; + case XK_BackSpace: + return '\b'; + case XK_Linefeed: + return '\r'; + case XK_Return: + return '\n'; + case XK_Delete: + return 127; + case XK_Tab: + return '\t'; + default: + break; + } + return sym; +} + +static void handle_event(XEvent *ev) +{ + KeySym sym; + + switch(ev->type) { + case MapNotify: + mapped = 1; + break; + case UnmapNotify: + mapped = 0; + break; + case ConfigureNotify: + if(ev->xconfigure.width != win_width || ev->xconfigure.height != win_height) { + win_width = ev->xconfigure.width; + win_height = ev->xconfigure.height; + reshape(ev->xconfigure.width, ev->xconfigure.height); + } + break; + + case ClientMessage: + if(ev->xclient.message_type == xa_wm_proto) { + if(ev->xclient.data.l[0] == xa_wm_del_win) { + quit = 1; + } + } + break; + + case Expose: + /*upd_pending = 1;*/ + break; + + case KeyPress: + case KeyRelease: + modstate = ev->xkey.state & (ShiftMask | ControlMask | Mod1Mask); + if(!(sym = XLookupKeysym(&ev->xkey, 0))) { + break; + } + sym = translate_keysym(sym); + if(ev->type == KeyPress) { + keydown(sym, ev->xkey.x, ev->xkey.y); + } else { + keyup(sym, ev->xkey.x, ev->xkey.y); + } + break; + + case ButtonPress: + case ButtonRelease: + modstate = ev->xbutton.state & (ShiftMask | ControlMask | Mod1Mask); + button(ev->xbutton.button - Button1, ev->type == ButtonPress, + ev->xbutton.x, ev->xbutton.y); + break; + + case MotionNotify: + motion(ev->xmotion.x, ev->xmotion.y); + break; + + default: + break; + } +} + +static void set_window_title(const char *title) +{ + XTextProperty tprop; + if(!XStringListToTextProperty((char**)&title, 1, &tprop)) { + return; + } + XSetWMName(dpy, win, &tprop); + XFree(tprop.value); +}