# HG changeset patch # User John Tsiombikas # Date 1305350770 -10800 # Node ID edbfc96fe80d8dfc8de116e5e07346df9b11c914 # Parent 0cb438c86b9822cf07b6082f0d1318a2fd446925 glut wsys thingy and stuff... diff -r 0cb438c86b98 -r edbfc96fe80d Makefile.in --- a/Makefile.in Fri May 13 09:44:21 2011 +0300 +++ b/Makefile.in Sat May 14 08:26:10 2011 +0300 @@ -23,7 +23,7 @@ AR = ar CC = gcc CFLAGS = -pedantic -Wall -g -fPIC -Iinclude -Isrc -LDFLAGS = -lX11 +LDFLAGS = $(wsys_libs) .PHONY: all all: $(lib_so) $(lib_a) diff -r 0cb438c86b98 -r edbfc96fe80d README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/README Sat May 14 08:26:10 2011 +0300 @@ -0,0 +1,14 @@ +Author: John Tsiombikas +Contact: nuclear@member.fsf.org + +Adding window system modules +---------------------------- +Window system modules are detected automatically by configure. For this to work, +each module must be a single file in src/ called wsys_whatever.c. + +Somewhere in the module, there must be a comment of the form: /* link-with: +whatever */ where the whatever part is passed to the linker, and is also used to +determine at compile time if the module should be enabled. + +Finally the module source code must start by including "config.h", and the rest +of it from that point on must be in a big ifdef USE_WSYS_MODULE_WHATEVER block. diff -r 0cb438c86b98 -r edbfc96fe80d configure --- a/configure Fri May 13 09:44:21 2011 +0300 +++ b/configure Sat May 14 08:26:10 2011 +0300 @@ -1,27 +1,85 @@ #!/bin/sh -gen_module_init() +cfgfile=src/config.h +modfile=src/modules.c + +get_depline() { - # collect all src/wsys_whatever.c files - modules=`ls src/wsys_*.c 2>/dev/null | sort | sed 's/src\/wsys_//' | sed 's/\.c//'` - - echo "/* this file is generated by $0, do not edit */" - for m in $modules; do - echo "void sgl_register_$m();" - done - - echo - echo 'void sgl_modules_init(void)' - echo '{' - - for m in $modules; do - echo " sgl_register_$m();" - done - - echo '}' + grep 'link-with:' $1 | sed 's/^.*link-with: \?\(.*\) \?\*\//\1/' } -gen_module_init >src/modules.c +get_usedef() +{ + grep '#ifdef *USE_WSYS_MODULE' $1 | sed 's/^.*\(USE_WSYS_MODULE_.*\)/\1/' +} +try_link() +{ + srcfile=/tmp/sgl-trylink.c + aout=/tmp/sgl-a.out + + echo 'int main(void) { return 0; }' >$srcfile + cc -o $aout $srcfile $1 >/dev/null 2>/dev/null +} + +# write beginning of config.h +echo '#ifndef CONFIG_H_' >$cfgfile +echo '#define CONFIG_H_' >>$cfgfile +echo >>$cfgfile + +# write beginning of modules.c +echo "/* this file is generated by $0, do not edit */" >$modfile +echo >>$modfile +echo 'void sgl_modules_init(void)' >>$modfile +echo '{' >>$modfile + + +# start scanning for modules +echo 'Looking for usable window system modules ...' + +# collect all src/wsys_whatever.c files +all_files=`ls src/wsys_*.c 2>/dev/null` + +for m in $all_files; do + # extract USE_WSYS_MODULE_* define + def=`get_usedef $m` + + # extract link-with line + dep=`get_depline $m` + name=`echo $m | sort | sed 's/src\/wsys_//' | sed 's/\.c//'` + echo -n "-> trying module $name (needs: $dep) ... " + + if try_link $dep; then + echo ok + + libs="$libs $dep" + + # emmit the USE_ define in config.h + echo "#define $def" >>$cfgfile + echo >>$cfgfile + + # make the registration call in modules.c + echo " void sgl_register_$name();" >>$modfile + echo " sgl_register_$name();" >>$modfile + echo >>$modfile + else + echo failed + fi +done +echo "Will link with: $libs" + +# wrap up the modules.c file +echo '}' >>$modfile + +# wrap up the config.h file +echo '#endif /* CONFIG_H_ */' >>$cfgfile + +# generate makefile +echo Generating makefile ... + +# hardcode prefix for now, too lazy to actually add an option... echo 'PREFIX = /usr/local' >Makefile +echo "wsys_libs = $libs" >>Makefile cat Makefile.in >>Makefile + +echo 'Configuration complete. Run make (or gmake) to compile.' diff -r 0cb438c86b98 -r edbfc96fe80d include/sgl.h --- a/include/sgl.h Fri May 13 09:44:21 2011 +0300 +++ b/include/sgl.h Sat May 14 08:26:10 2011 +0300 @@ -37,6 +37,19 @@ SGL_RIGHT_BUTTON }; +/* these values happen to coincide with X11 keysyms */ +#define SGL_KEY_LSHIFT 0xffe1 +#define SGL_KEY_RSHIFT 0xffe2 +#define SGL_KEY_LCONTROL 0xffe3 +#define SGL_KEY_RCONTROL 0xffe4 +#define SGL_KEY_LALT 0xffe9 +#define SGL_KEY_RALT 0xffea + +/* for the sgl_modifiers bitmask */ +#define SGL_MOD_SHIFT 1 +#define SGL_MOD_CONTROL 2 +#define SGL_MOD_ALT 4 + int sgl_init(void); void sgl_quit(void); @@ -52,6 +65,8 @@ void sgl_redisplay(void); void sgl_swap_buffers(void); +int sgl_modifiers(void); + int sgl_process_events(void); void sgl_event_loop(void); diff -r 0cb438c86b98 -r edbfc96fe80d src/sgl.c --- a/src/sgl.c Fri May 13 09:44:21 2011 +0300 +++ b/src/sgl.c Sat May 14 08:26:10 2011 +0300 @@ -9,6 +9,7 @@ { sgl_modules_init(); sgl_sort_modules(); + sgl_print_modules(); if(!(ws = sgl_wsys_module())) { return -1; diff -r 0cb438c86b98 -r edbfc96fe80d src/wsys.c --- a/src/wsys.c Fri May 13 09:44:21 2011 +0300 +++ b/src/wsys.c Sat May 14 08:26:10 2011 +0300 @@ -1,11 +1,13 @@ #include +#include +#include #include "wsys.h" static struct wsys_module *merge(struct wsys_module *list1, struct wsys_module *list2); static struct wsys_module *msort(struct wsys_module *list, int count); -struct wsys_module *wslist; +struct wsys_module *wslist, *sel; int wscount; int sgl_register_module(struct wsys_module *ws) @@ -21,9 +23,38 @@ wslist = msort(wslist, wscount); } +void sgl_print_modules(void) +{ + struct wsys_module *ws = wslist; + + printf("window system modules:\n"); + while(ws) { + printf("- %s\n", ws->name); + ws = ws->next; + } +} + struct wsys_module *sgl_wsys_module(void) { - return wslist; + if(!sel) { + char *modname; + if((modname = getenv("SGL_MODULE"))) { + struct wsys_module *ws = wslist; + while(ws) { + if(strcmp(ws->name, modname) == 0) { + sel = ws; + break; + } + ws = ws->next; + } + if(!sel) { + sel = wslist; + } + } else { + sel = wslist; + } + } + return sel; } #define APPEND(node) \ diff -r 0cb438c86b98 -r edbfc96fe80d src/wsys.h --- a/src/wsys.h Fri May 13 09:44:21 2011 +0300 +++ b/src/wsys.h Sat May 14 08:26:10 2011 +0300 @@ -20,6 +20,8 @@ void (*redisplay)(void); void (*swap_buffers)(void); + int (*get_modifiers)(void); + void (*set_event)(int idx, int enable); int (*process_events)(void); @@ -28,6 +30,7 @@ int sgl_register_module(struct wsys_module *ws); void sgl_sort_modules(void); +void sgl_print_modules(void); struct wsys_module *sgl_wsys_module(void); void dbg(void); diff -r 0cb438c86b98 -r edbfc96fe80d src/wsys_glut.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/wsys_glut.c Sat May 14 08:26:10 2011 +0300 @@ -0,0 +1,367 @@ +/* SimplyGL window system module for GLUT */ +/* link-with: -lglut */ + +#include "config.h" + +#ifdef USE_WSYS_MODULE_GLUT + +#include +#ifndef __APPLE__ +#include +#undef FREEGLUT +#ifdef FREEGLUT +#include +#endif /* freeglut */ + +#else /* apple */ +#include +#endif + +#include "sgl.h" +#include "wsys.h" + +struct window { + int id; + struct window *next; +}; + +static int init(void); +static void shutdown(void); + +/* video mode switching */ +static int set_vidmode(int xsz, int ysz); +static int get_vidmode(int *xsz, int *ysz); + +/* create/destroy windows */ +static int create_window(int xsz, int ysz, unsigned int flags); +static void close_window(int id); + +/* window management */ +static int set_active(int id); +static int set_title(const char *str); +static void redisplay(void); +static void swap_buffers(void); + +static int get_modifiers(void); + +/* event handling and friends */ +static void set_event(int idx, int enable); +static int process_events(void); + +/* callbacks */ +static void disp_cb(void); +static void reshape_cb(int x, int y); +static void keyb_down_cb(unsigned char c, int x, int y); +static void keyb_up_cb(unsigned char c, int x, int y); +static void special_down_cb(int c, int x, int y); +static void special_up_cb(int c, int x, int y); +static void mouse_cb(int bn, int state, int x, int y); +static void motion_cb(int x, int y); +static void passive_cb(int x, int y); +static void idle_cb(void); + + +static struct wsys_module ws = { + "glut", 1, + init, + shutdown, + set_vidmode, + get_vidmode, + create_window, + close_window, + set_active, + set_title, + redisplay, + swap_buffers, + get_modifiers, + set_event, + process_events, + 0 +}; + +#ifndef FREEGLUT +static jmp_buf jbuf; +#endif + +static struct window *winlist; + + +/* this is the only exported function, everything else should be static */ +void sgl_register_glut(void) +{ + sgl_register_module(&ws); +} + +static int init(void) +{ + char *argv[] = { "simplygl", 0 }; + int argc = 1; + + glutInit(&argc, argv); + return 0; +} + +static void shutdown(void) +{ + struct window *win = winlist; + + while(win) { + int id = win->id; + win = win->next; + + close_window(id); + } + winlist = 0; +} + +static int set_vidmode(int xsz, int ysz) +{ + /* TODO */ + return 0; +} + +static int get_vidmode(int *xsz, int *ysz) +{ + /* TODO */ + return 0; +} + +static int create_window(int xsz, int ysz, unsigned int flags) +{ + struct window *win; + unsigned int glut_flags = GLUT_RGBA; + + if(flags & SGL_DOUBLE) { + glut_flags |= GLUT_DOUBLE; + } + if(flags & SGL_DEPTH) { + glut_flags |= GLUT_DEPTH; + } + if(flags & SGL_STENCIL) { + glut_flags |= GLUT_STENCIL; + } + if(flags & SGL_STEREO) { + glut_flags |= GLUT_STEREO; + } + if(flags & SGL_MULTISAMPLE) { + glut_flags |= GLUT_MULTISAMPLE; + } + + if(!(win = malloc(sizeof *win))) { + return -1; + } + + glutInitDisplayMode(glut_flags); + glutInitWindowSize(xsz, ysz); + if((win->id = glutCreateWindow("OpenGL/GLUT")) <= 0) { + free(win); + return -1; + } + + win->next = winlist; + winlist = win; + return win->id; +} + +static void close_window(int id) +{ + struct window dummy, *win, *prev; + + dummy.next = win = winlist; + prev = &dummy; + + while(win) { + if(win->id == id) { + prev->next = win->next; + free(win); + break; + } + win = win->next; + } + + glutDestroyWindow(id); +} + +static int set_active(int id) +{ + glutSetWindow(id); + return 0; +} + +static int set_title(const char *str) +{ + glutSetWindowTitle(str); + glutSetIconTitle(str); + return 0; +} + +static void redisplay(void) +{ + glutPostRedisplay(); +} + +static void swap_buffers(void) +{ + glutSwapBuffers(); +} + +static int get_modifiers(void) +{ + return glutGetModifiers(); +} + +static void set_event(int idx, int enable) +{ + switch(idx) { + case SGL_DISPLAY: + glutDisplayFunc(enable ? disp_cb : 0); + break; + case SGL_RESHAPE: + glutReshapeFunc(enable ? reshape_cb : 0); + break; + case SGL_KEYBOARD: + glutKeyboardFunc(enable ? keyb_down_cb : 0); + glutKeyboardUpFunc(enable ? keyb_up_cb : 0); + glutSpecialFunc(enable ? special_down_cb : 0); + glutSpecialUpFunc(enable ? special_up_cb : 0); + break; + case SGL_MOUSE: + glutMouseFunc(enable ? mouse_cb : 0); + break; + case SGL_MOTION: + glutMotionFunc(enable ? motion_cb : 0); + break; + case SGL_PASSIVE: + glutPassiveMotionFunc(enable ? passive_cb : 0); + break; + case SGL_IDLE: + glutIdleFunc(enable ? idle_cb : 0); + break; + default: + break; + } +} + +static int process_events(void) +{ +#ifdef FREEGLUT + glutMainLoopEvent(); +#else + if(setjmp(jbuf) == 0) { + glutMainLoop(); + } + /* ok ... what happens is any callback that kicks in will set the idle func + * if it's not set, and then the idle func will longjmp right back here... + */ +#endif + return 0; +} + +static void disp_cb(void) +{ + sgl_display_callback_t func = sgl_get_callback(SGL_DISPLAY); + func(); + +#ifndef FREEGLUT + glutIdleFunc(idle_cb); +#endif +} + +static void reshape_cb(int x, int y) +{ + sgl_reshape_callback_t func = sgl_get_callback(SGL_RESHAPE); + func(x, y); + +#ifndef FREEGLUT + glutIdleFunc(idle_cb); +#endif +} + +static void keyb_down_cb(unsigned char c, int x, int y) +{ + sgl_keyboard_callback_t func = sgl_get_callback(SGL_KEYBOARD); + func((int)c, 1); + +#ifndef FREEGLUT + glutIdleFunc(idle_cb); +#endif +} + +static void keyb_up_cb(unsigned char c, int x, int y) +{ + sgl_keyboard_callback_t func = sgl_get_callback(SGL_KEYBOARD); + func((int)c, 0); + +#ifndef FREEGLUT + glutIdleFunc(idle_cb); +#endif +} + +static void special_down_cb(int c, int x, int y) +{ + sgl_keyboard_callback_t func = sgl_get_callback(SGL_KEYBOARD); + func(c, 1); + +#ifndef FREEGLUT + glutIdleFunc(idle_cb); +#endif +} + +static void special_up_cb(int c, int x, int y) +{ + sgl_keyboard_callback_t func = sgl_get_callback(SGL_KEYBOARD); + func(c, 0); + +#ifndef FREEGLUT + glutIdleFunc(idle_cb); +#endif +} + +static void mouse_cb(int bn, int state, int x, int y) +{ + sgl_mouse_callback_t func = sgl_get_callback(SGL_MOUSE); + func(0, bn, state, x, y); + +#ifndef FREEGLUT + glutIdleFunc(idle_cb); +#endif +} + +static void motion_cb(int x, int y) +{ + sgl_motion_callback_t func = sgl_get_callback(SGL_MOTION); + func(0, x, y); + +#ifndef FREEGLUT + glutIdleFunc(idle_cb); +#endif +} + +static void passive_cb(int x, int y) +{ + sgl_passive_callback_t func = sgl_get_callback(SGL_PASSIVE); + func(0, x, y); + +#ifndef FREEGLUT + glutIdleFunc(idle_cb); +#endif +} + +static void idle_cb(void) +{ + sgl_idle_callback_t func = sgl_get_callback(SGL_IDLE); + if(func) { + func(); +#ifndef FREEGLUT + } else { + /* this was just the longjmp trick so restore the lack of idle func */ + glutIdleFunc(0); +#endif + } + +#ifndef FREEGLUT + longjmp(jbuf, 0); +#endif +} + +#endif /* USE_WSYS_MODULE_GLUT */ diff -r 0cb438c86b98 -r edbfc96fe80d src/wsys_x11.c --- a/src/wsys_x11.c Fri May 13 09:44:21 2011 +0300 +++ b/src/wsys_x11.c Sat May 14 08:26:10 2011 +0300 @@ -1,4 +1,12 @@ +/* SimplyGL window system module for X11/GLX */ +/* link-with: -lX11 */ + +#include "config.h" + +#ifdef USE_WSYS_MODULE_X11 + #include +#include #include #include #include "sgl.h" @@ -37,12 +45,15 @@ static void redisplay(void); static void swap_buffers(void); +static int get_modifiers(void); + /* event handling and friends */ static void set_bits(long *mask, long bits); 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 void process_key(KeySym sym, int state); static int translate_keysym(KeySym sym); static struct wsys_module ws = { @@ -57,6 +68,7 @@ set_title, redisplay, swap_buffers, + get_modifiers, set_event, process_events, 0 @@ -68,6 +80,7 @@ static Atom xa_wm_prot, xa_wm_del_win; static struct window *winlist; static struct window *active_win, *prev_active; +static int modkeys; /* this is the only exported function, everything else should be static */ void sgl_register_x11(void) @@ -355,6 +368,11 @@ glXSwapBuffers(dpy, active_win->win); } +static int get_modifiers(void) +{ + return modkeys; +} + static void set_bits(long *mask, long bits) { *mask |= bits; @@ -449,6 +467,7 @@ int state; struct window *win; void (*func)(); + KeySym sym; if((win = find_window(xev->xany.window))) { activate_window(win); @@ -505,8 +524,10 @@ case KeyRelease: state = 0; } + sym = XLookupKeysym(&xev->xkey, 0); + process_key(sym, state); + if((func = sgl_get_callback(SGL_KEYBOARD))) { - KeySym sym = XLookupKeysym(&xev->xkey, 0); func(translate_keysym(sym), state); } break; @@ -540,9 +561,35 @@ return 0; } +static void process_key(KeySym sym, int state) +{ + switch(sym) { + case XK_Shift_L: + case XK_Shift_R: + modkeys = state ? (modkeys | SGL_MOD_SHIFT) : (modkeys & ~SGL_MOD_SHIFT); + break; + + case XK_Control_L: + case XK_Control_R: + modkeys = state ? (modkeys | SGL_MOD_CONTROL) : (modkeys & ~SGL_MOD_CONTROL); + break; + + case XK_Alt_L: + case XK_Alt_R: + modkeys = state ? (modkeys | SGL_MOD_ALT) : (modkeys & ~SGL_MOD_ALT); + break; + + default: + break; + } +} + static int translate_keysym(KeySym sym) { if(sym < 256) { + if(isalpha(sym) && (modkeys & SGL_MOD_SHIFT)) { + sym = toupper(sym); + } return sym; } @@ -562,3 +609,5 @@ } return (int)sym; } + +#endif /* USE_WSYS_MODULE_X11 */