# HG changeset patch # User John Tsiombikas # Date 1305262187 -10800 # Node ID 0570e27e5ebc1f10245837abeb7cb7e4172702e8 # Parent 648f8604d2b2510c1d627f6263823fdaf597218e pretty much done with the basic functionality and GLX shit diff -r 648f8604d2b2 -r 0570e27e5ebc Makefile.in --- a/Makefile.in Thu May 12 11:04:10 2011 +0300 +++ b/Makefile.in Fri May 13 07:49:47 2011 +0300 @@ -8,7 +8,7 @@ somajor = 0 sominor = 0 -lib_so_unix = $(soname).$(minor) +lib_so_unix = $(soname).$(sominor) lib_so_mac = libsgl.dylib sharedopt_unix = -shared -Wl,-soname,$(soname) @@ -23,6 +23,7 @@ AR = ar CC = gcc CFLAGS = -pedantic -Wall -g -fPIC -Iinclude -Isrc +LDFLAGS = -lX11 .PHONY: all all: $(lib_so) $(lib_a) @@ -31,7 +32,7 @@ $(AR) rcs $@ $(obj) $(lib_so): $(obj) - $(CC) $(sharedopt_$(sys)) -o $@ $(obj) + $(CC) $(sharedopt_$(sys)) -o $@ $(obj) $(LDFLAGS) -include $(dep) diff -r 648f8604d2b2 -r 0570e27e5ebc include/sgl.h --- a/include/sgl.h Thu May 12 11:04:10 2011 +0300 +++ b/include/sgl.h Fri May 13 07:49:47 2011 +0300 @@ -21,8 +21,14 @@ SGL_NUM_CALLBACKS }; +enum { + SGL_LEFT_BUTTON, + SGL_MIDDLE_BUTTON, + SGL_RIGHT_BUTTON +}; + int sgl_init(void); -void sgl_shutdown(void); +void sgl_quit(void); int sgl_set_video_mode(int xsz, int ysz); int sgl_get_video_mode(int *xsz, int *ysz); @@ -33,8 +39,11 @@ int sgl_set_active(int id); int sgl_set_title(const char *str); +void sgl_redisplay(void); +void sgl_swap_buffers(void); + int sgl_process_events(void); -int sgl_event_loop(void); +void sgl_event_loop(void); int sgl_push_callbacks(void); int sgl_pop_callbacks(void); diff -r 648f8604d2b2 -r 0570e27e5ebc src/cb.c --- a/src/cb.c Thu May 12 11:04:10 2011 +0300 +++ b/src/cb.c Fri May 13 07:49:47 2011 +0300 @@ -48,9 +48,15 @@ notify_wsys(); } -void sgl_callback(int idx, void (*func)()) +void sgl_set_callback(int idx, void (*func)()) { + struct wsys_module *ws; + cb->func[idx] = func; + + if((ws = sgl_wsys_module())) { + ws->set_event(idx, func != 0); + } } void (*sgl_get_callback(int idx))() diff -r 648f8604d2b2 -r 0570e27e5ebc src/log.c --- a/src/log.c Thu May 12 11:04:10 2011 +0300 +++ b/src/log.c Fri May 13 07:49:47 2011 +0300 @@ -17,5 +17,7 @@ vfprintf(fp, fmt, ap); va_end(ap); - fclose(fp); + if(fp != stderr) { + fclose(fp); + } } diff -r 648f8604d2b2 -r 0570e27e5ebc src/sgl.c --- a/src/sgl.c Thu May 12 11:04:10 2011 +0300 +++ b/src/sgl.c Fri May 13 07:49:47 2011 +0300 @@ -1,13 +1,13 @@ #include "sgl.h" #include "wsys.h" -void sgl_register_modules(void); +void sgl_modules_init(void); static struct wsys_module *ws; int sgl_init(void) { - sgl_register_modules(); + sgl_modules_init(); sgl_sort_modules(); if(!(ws = sgl_wsys_module())) { @@ -16,7 +16,7 @@ return ws->init(); } -void sgl_shutdown(void) +void sgl_quit(void) { ws->shutdown(); } @@ -51,7 +51,22 @@ return ws->set_title(str); } +void sgl_redisplay(void) +{ + ws->redisplay(); +} + +void sgl_swap_buffers(void) +{ + ws->swap_buffers(); +} + int sgl_process_events(void) { return ws->process_events(); } + +void sgl_event_loop(void) +{ + while(ws->process_events() == 0); +} diff -r 648f8604d2b2 -r 0570e27e5ebc src/wsys.h --- a/src/wsys.h Thu May 12 11:04:10 2011 +0300 +++ b/src/wsys.h Fri May 13 07:49:47 2011 +0300 @@ -17,12 +17,12 @@ int (*set_active)(int); int (*set_title)(const char*); + void (*redisplay)(void); + void (*swap_buffers)(void); + void (*set_event)(int idx, int enable); int (*process_events)(void); - void (*redisplay)(void); - void (*swap_buffers)(void); - struct wsys_module *next; }; diff -r 648f8604d2b2 -r 0570e27e5ebc src/wsys_x11.c --- a/src/wsys_x11.c Thu May 12 11:04:10 2011 +0300 +++ b/src/wsys_x11.c Fri May 13 07:49:47 2011 +0300 @@ -5,10 +5,14 @@ #include "wsys.h" #include "log.h" + struct window { Window win; GLXContext ctx; + int width, height; + int mapped; long evmask; + int redisp_pending; struct window *next; }; @@ -27,6 +31,8 @@ /* window management */ static int set_active(int id); +static struct window *find_window(int id); +static int activate_window(struct window *win); static int set_title(const char *str); static void redisplay(void); static void swap_buffers(void); @@ -36,7 +42,8 @@ static void clear_bits(long *mask, long bits); static void set_event(int idx, int enable); static int process_events(void); - +static int handle_event(XEvent *xev); +static int translate_keysym(KeySym sym); static struct wsys_module ws = { "x11-glx", 0, @@ -60,7 +67,7 @@ static int scr; static Atom xa_wm_prot, xa_wm_del_win; static struct window *winlist; -static struct window *active_win; +static struct window *active_win, *prev_active; /* this is the only exported function, everything else should be static */ void sgl_register_x11(void) @@ -70,7 +77,13 @@ static int init(void) { + if(dpy) { + sgl_log("warning: double init\n"); + return 0; + } + winlist = 0; + active_win = prev_active = 0; if(!(dpy = XOpenDisplay(0))) { sgl_log("failed to open X display: %s\n", XDisplayName(0)); @@ -87,6 +100,10 @@ static void shutdown(void) { + if(!dpy) { + return; + } + while(winlist) { struct window *win = winlist; winlist = winlist->next; @@ -171,9 +188,13 @@ wnode->win = win; wnode->ctx = ctx; + wnode->width = xsz; + wnode->height = ysz; + wnode->mapped = 0; wnode->evmask = evmask; + wnode->redisp_pending = 1; wnode->next = winlist; - winlist->next = wnode; + winlist = wnode; if(!active_win) { set_active(win); @@ -261,22 +282,37 @@ static int set_active(int id) { + struct window *win = find_window(id); + if(!win) { + sgl_log("no such window: %d\n", id); + return -1; + } + /* only the user calls this, so don't revert this selection */ + prev_active = win; + return activate_window(win); +} + +static struct window *find_window(int id) +{ struct window *win = winlist; while(win) { if(win->win == id) { - if(glXMakeCurrent(dpy, win->win, win->ctx) == False) { - sgl_log("failed to activate window %d\n", id); - return -1; - } - active_win = win; - return 0; + return win; } win = win->next; } + return 0; +} - sgl_log("no such window: %d\n", id); - return -1; +static int activate_window(struct window *win) +{ + if(glXMakeCurrent(dpy, win->win, win->ctx) == False) { + sgl_log("failed to activate window %d\n", (int)win->win); + return -1; + } + active_win = win; + return 0; } static int set_title(const char *str) @@ -300,7 +336,7 @@ static void swap_buffers(void) { - glXSwapBuffers(dpy, active_win->ctx); + glXSwapBuffers(dpy, active_win->win); } static void set_bits(long *mask, long bits) @@ -350,76 +386,163 @@ { XEvent xev; void (*func)(); - int state; + struct window *win; + prev_active = active_win; + + win = winlist; + while(win) { + if(win->redisp_pending && (func = sgl_get_callback(SGL_DISPLAY))) { + activate_window(win); + func(); + win->redisp_pending = 0; + } + win = win->next; + } + + func = sgl_get_callback(SGL_IDLE); + if(!func) { + XNextEvent(dpy, &xev); + XPutBackEvent(dpy, &xev); + } + + /* process all pending events... */ while(XPending(dpy)) { XNextEvent(dpy, &xev); + if(handle_event(&xev) == -1) { + return -1; + } - switch(xev.type) { - case Expose: - if(xev.xexpose.count == 0) { - if((func = sgl_get_callback(SGL_DISPLAY))) { - func(); - active_win->redisp_pending = 0; + if(!dpy) { + return -1; + } + } + + if(func) { + /* ... and then call the idle function */ + func(); + } + + activate_window(prev_active); + return 0; +} + +/* returns 0, or -1 when the last window gets closed */ +static int handle_event(XEvent *xev) +{ + int state; + struct window *win; + void (*func)(); + + if((win = find_window(xev->xany.window))) { + activate_window(win); + } else { + return 0; + } + + switch(xev->type) { + case MapNotify: + active_win->mapped = 1; + break; + + case UnmapNotify: + active_win->mapped = 0; + break; + + case Expose: + if(active_win->mapped && xev->xexpose.count == 0) { + if((func = sgl_get_callback(SGL_DISPLAY))) { + func(); + active_win->redisp_pending = 0; + } + } + break; + + case MotionNotify: + if(xev->xmotion.state) { + func = sgl_get_callback(SGL_MOTION); + } else { + func = sgl_get_callback(SGL_PASSIVE); + } + if(func) { + func(xev->xmotion.x, xev->xmotion.y); + } + break; + + case ButtonPress: + if(1) { + state = 1; + } else { + case ButtonRelease: + state = 0; + } + if((func = sgl_get_callback(SGL_MOUSE))) { + int bn = xev->xbutton.button - 1; + func(bn, state, xev->xbutton.x, xev->xbutton.y); + } + break; + + case KeyPress: + if(1) { + state = 1; + } else { + case KeyRelease: + state = 0; + } + if((func = sgl_get_callback(SGL_KEYBOARD))) { + KeySym sym = XLookupKeysym(&xev->xkey, 0); + func(translate_keysym(sym), state); + } + break; + + case ConfigureNotify: + if((func = sgl_get_callback(SGL_RESHAPE))) { + if(xev->xconfigure.width != active_win->width || xev->xconfigure.height != active_win->height) { + active_win->width = xev->xconfigure.width; + active_win->height = xev->xconfigure.height; + + func(xev->xconfigure.width, xev->xconfigure.height); + } + } + break; + + case ClientMessage: + if(xev->xclient.message_type == xa_wm_prot) { + if(xev->xclient.data.l[0] == xa_wm_del_win) { + close_window(active_win->win); + if(!active_win) { + return -1; } } - break; + } + break; - case MotionNotify: - if(xev.xmotion.state) { - func = sgl_get_callback(SGL_MOTION); - } else { - func = sgl_get_callback(SGL_PASSIVE); - } - if(func) { - func(xev.xmotion.x, xev.xmotion.y); - } - break; + default: + break; + } - case ButtonPress: - if(1) { - state = 1; - } else { - case ButtonRelease: - state = 0; - } - if((func = sgl_get_callback(SGL_MOUSE))) { - int bn = xev.xbutton.button - 1; - func(bn, state, xev.xbutton.x, xev.xbutton.y); - } - break; - - case KeyPress: - if(1) { - state = 1; - } else { - case KeyRelease: - state = 0; - } - if((func = sgl_get_callback(SGL_KEYBOARD))) { - KeySym sym = XLookupKeysym(xev.xkey, 0); - func(sym, state); - /* XXX */ - } - break; - - case ConfigureNotify: - if((func = sgl_get_callback(SGL_RESHAPE))) { - func(xev.xconfigure.width, xev.xconfigure.height); - } - break; - } - - case ClientMessage: - if(xev.xclient.message_type == xa_wm_prot) { - if(xev.xclient.data.l[0] == xa_wm_del_win) { - close_window(active_win->win); - if(!active_win) { - return 1; - } - } - } - break; - } return 0; } + +static int translate_keysym(KeySym sym) +{ + if(sym < 256) { + return sym; + } + + switch(sym) { + case XK_BackSpace: + return '\b'; + case XK_Tab: + return '\t'; + case XK_Linefeed: + return '\r'; + case XK_Return: + return '\n'; + case XK_Escape: + return 27; + default: + break; + } + return (int)sym; +} diff -r 648f8604d2b2 -r 0570e27e5ebc tests/simple/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/simple/Makefile Fri May 13 07:49:47 2011 +0300 @@ -0,0 +1,1 @@ +../tests-makefile \ No newline at end of file diff -r 648f8604d2b2 -r 0570e27e5ebc tests/simple/simple.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/simple/simple.c Fri May 13 07:49:47 2011 +0300 @@ -0,0 +1,83 @@ +#include +#include +#include +#include "sgl.h" + +void disp(void); +void reshape(int x, int y); +void keyb(int key, int state); +void mouse(int bn, int state, int x, int y); +void motion(int x, int y); + + +int main(void) +{ + if(sgl_init() == -1) { + return 1; + } + + sgl_create_window(640, 480, SGL_DOUBLE | SGL_DEPTH); + + sgl_set_callback(SGL_DISPLAY, disp); + sgl_set_callback(SGL_RESHAPE, reshape); + sgl_set_callback(SGL_KEYBOARD, keyb); + sgl_set_callback(SGL_MOUSE, mouse); + sgl_set_callback(SGL_MOTION, motion); + + sgl_event_loop(); + sgl_quit(); + return 0; +} + + +void disp(void) +{ + printf("redisplay\n"); + + glClearColor(0.2, 0.2, 0.2, 1); + glClear(GL_COLOR_BUFFER_BIT); + + glBegin(GL_QUADS); + glColor3f(1, 0, 0); + glVertex2f(-1, -1); + glColor3f(0, 1, 0); + glVertex2f(1, -1); + glColor3f(0, 0, 1); + glVertex2f(1, 1); + glColor3f(1, 1, 0); + glVertex2f(-1, 1); + glEnd(); + + sgl_swap_buffers(); +} + +void reshape(int x, int y) +{ + printf("reshape: %dx%d\n", x, y); + glViewport(0, 0, x, y); +} + +void keyb(int key, int state) +{ + char *ststr = state ? "pressed" : "released"; + + if(key < 0xff && isprint(key)) { + printf("keyboard: '%c' %s\n", (char)key, ststr); + } else { + printf("keyboard: %x %s\n", key, ststr); + } + + if(key == 27) { + sgl_quit(); + } +} + +void mouse(int bn, int state, int x, int y) +{ + printf("mouse: button%d %s (ptr: %d %d)\n", bn, state ? "pressed" : "released", x, y); +} + +void motion(int x, int y) +{ + printf("mouse dragged to: (%d %d)\n", x, y); +} diff -r 648f8604d2b2 -r 0570e27e5ebc tests/tests-makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/tests-makefile Fri May 13 07:49:47 2011 +0300 @@ -0,0 +1,21 @@ +name = $(shell pwd | sed 's/.*\///') +bin = $(name) +src = $(wildcard *.c) +obj = $(src:.c=.o) + +sgldir = ../.. + +CC = gcc +CFLAGS = -pedantic -Wall -g -I$(sgldir)/include +LDFLAGS = -L. -Wl,-rpath=. -lsgl -lGL -lGLU -lm + +$(bin): $(obj) libsgl.so + $(CC) -o $@ $(obj) $(LDFLAGS) + +libsgl.so: $(sgldir)/libsgl.so.0.0 + ln -s $< $@.0 + ln -s $< $@ + +.PHONY: clean +clean: + rm -f $(obj) $(bin)