Import from seb-0515.tar.gz
[neverball-archive.git] / src / libglw / glw.c
blob93723cf56b40949dec1bfdfdab186e48958a2fa7
1 #include <stdlib.h>
2 #include <GL/glx.h>
3 #include <X11/Xutil.h>
5 #include "glw.h"
7 /*--------------------------------------------------------------------*/
9 static Display *dpy;
10 static Window win;
11 static XVisualInfo *xvi;
12 static Atom del;
13 static XSizeHints *siz;
14 static GLXContext ctx;
16 static int center_x = 0;
17 static int center_y = 0;
19 static int last_x = 0;
20 static int last_y = 0;
21 static int height = 0;
23 /*--------------------------------------------------------------------*/
25 static int glx_init_dpy(void)
27 if ((dpy = XOpenDisplay(NULL)) == NULL)
28 return 0;
30 if (glXQueryExtension(dpy, NULL, NULL) == False)
31 return 0;
33 return 1;
36 static int glx_init_xvi(int e)
38 int attributes[] = {
39 GLX_STEREO,
40 GLX_RGBA,
41 GLX_DOUBLEBUFFER,
42 GLX_DEPTH_SIZE, 16,
43 None
46 int *p = (e == 2) ? attributes : attributes + 1;
48 if ((xvi = glXChooseVisual(dpy, DefaultScreen(dpy), p)) == NULL)
49 return 0;
51 if (xvi->class != TrueColor)
52 return 0;
54 return 1;
58 static GLboolean glx_init_dec(void)
60 unsigned long hint[5] = { 2, 0, 0, 0, 0 };
61 Atom prop;
63 if (!(prop = XInternAtom(dpy, "_MOTIF_WM_HINTS", True)))
64 return GL_FALSE;
66 XChangeProperty(dpy, win, prop, prop, 32, PropModeReplace,
67 (unsigned char *) hint, 5);
69 return GL_TRUE;
72 static int glx_init_win(int w, int h)
74 int W = w ? w : DisplayWidth (dpy, xvi->screen);
75 int H = h ? h : DisplayHeight(dpy, xvi->screen);
77 Window root = RootWindow(dpy, xvi->screen);
78 Visual *vis = xvi->visual;
79 XSetWindowAttributes wa;
81 unsigned long valuemask = CWBorderPixel
82 | CWColormap
83 | CWEventMask;
85 wa.border_pixel = 0;
86 wa.colormap = XCreateColormap(dpy, root, vis, AllocNone);
87 wa.event_mask = StructureNotifyMask
88 | ExposureMask
89 | KeyPressMask
90 | KeyReleaseMask
91 | PointerMotionMask
92 | ButtonPressMask
93 | ButtonReleaseMask;
95 del = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
96 win = XCreateWindow(dpy, root, 0, 0, W, H, 0, xvi->depth,
97 InputOutput, vis, valuemask, &wa);
99 XSetWMProtocols(dpy, win, &del, 1);
101 return (w || h) ? 1 : glx_init_dec();
104 static int glx_init_hnt(const char *s)
106 int w = DisplayWidth (dpy, DefaultScreen(dpy));
107 int h = DisplayHeight(dpy, DefaultScreen(dpy));
109 siz = XAllocSizeHints();
111 if (siz)
113 siz->min_width = 160;
114 siz->min_height = 120;
115 siz->max_width = w;
116 siz->max_height = h;
118 siz->flags = PMinSize | PMaxSize;
120 XmbSetWMProperties(dpy, win, s, s, NULL, 0, siz, NULL, NULL);
122 return 1;
124 return 0;
127 static int glx_init_crs(void)
129 char bit[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
130 Pixmap pix;
131 Cursor crs;
132 XColor rgb;
134 rgb.red = 0;
135 rgb.green = 0;
136 rgb.blue = 0;
138 pix = XCreateBitmapFromData(dpy, win, bit, 8, 8);
139 crs = XCreatePixmapCursor(dpy, pix, pix, &rgb, &rgb, 0, 0);
141 XDefineCursor(dpy, win, crs);
142 XFreePixmap(dpy, pix);
144 return 1;
147 static int glx_init_ctx(void)
149 if ((ctx = glXCreateContext(dpy, xvi, NULL, True)) == NULL)
150 return 0;
152 if (glXMakeCurrent(dpy, win, ctx) == True)
153 return 1;
154 else
155 return 0;
158 /*--------------------------------------------------------------------*/
160 static int glx_client(XClientMessageEvent *e)
162 if (e->data.l[0] == del)
163 return GLW_CLOSE;
164 else
165 return 0;
168 static int glx_render(XExposeEvent *e)
170 if (e->count == 0)
171 return GLW_RENDER;
172 else
173 return 0;
176 static int glx_resize(XConfigureEvent *e)
178 height = e->height;
179 last_y = e->height;
180 last_x = e->width;
182 center_x = e->width / 2;
183 center_y = e->height / 2;
185 return GLW_RESIZE;
188 /*--------------------------------------------------------------------*/
190 static int glx_point(XMotionEvent *e)
192 last_x = e->x - center_x;
193 last_y = e->y - center_y;
195 XWarpPointer(dpy, None, win, 0, 0, 0, 0, center_x, center_y);
197 return GLW_MOTION;
200 static int glx_btn_d(XButtonEvent *e)
202 last_x = e->x;
203 last_y = e->y;
205 switch (e->button)
207 case 1: return GLW_L_BTN_D;
208 case 2: return GLW_M_BTN_D;
209 case 3: return GLW_R_BTN_D;
210 case 4: return GLW_WHEEL_D;
211 case 5: return GLW_WHEEL_U;
213 return 0;
216 static int glx_btn_u(XButtonEvent *e)
218 last_x = e->x;
219 last_y = e->y;
221 switch (e->button)
223 case 1: return GLW_L_BTN_U;
224 case 2: return GLW_M_BTN_U;
225 case 3: return GLW_R_BTN_U;
227 return 0;
230 /*--------------------------------------------------------------------*/
232 static int glx_key_d(XKeyEvent *e)
234 char c;
236 XLookupString(e, &c, 1, NULL, NULL);
237 last_x = (int) c;
239 return GLW_KEY_D;
242 static int glx_key_u(XKeyEvent *e)
244 char c;
246 XLookupString(e, &c, 1, NULL, NULL);
247 last_x = (int) c;
249 return GLW_KEY_U;
252 /*--------------------------------------------------------------------*/
254 int glw_create(const char *s, int w, int h, int e)
256 if (dpy == NULL)
258 if (!glx_init_dpy()) return 0;
259 if (!glx_init_xvi(e)) return 0;
260 if (!glx_init_win(w, h)) return 0;
261 if (!glx_init_hnt(s)) return 0;
262 if (!glx_init_crs()) return 0;
263 if (!glx_init_ctx()) return 0;
265 XMapWindow(dpy, win);
267 return 1;
270 void glw_delete(void)
272 if (dpy != NULL)
274 glXMakeCurrent(dpy, None, NULL);
275 glXDestroyContext(dpy, ctx);
277 XDestroyWindow(dpy, win);
278 XCloseDisplay(dpy);
280 dpy = NULL;
284 /*--------------------------------------------------------------------*/
286 int glw_update(int dirty, int wait)
288 XEvent e;
290 if (dirty) glXSwapBuffers(dpy, win);
292 if (wait || XPending(dpy) > 0)
294 XNextEvent(dpy, &e);
296 switch (e.type)
298 case ClientMessage: return glx_client(&e.xclient);
299 case Expose: return glx_render(&e.xexpose);
300 case ConfigureNotify: return glx_resize(&e.xconfigure);
302 case MotionNotify: return glx_point(&e.xmotion);
303 case ButtonPress: return glx_btn_d(&e.xbutton);
304 case ButtonRelease: return glx_btn_u(&e.xbutton);
305 case KeyPress: return glx_key_d(&e.xkey);
306 case KeyRelease: return glx_key_u(&e.xkey);
309 return 0;
312 int glw_x(void)
314 return last_x;
317 int glw_y(void)
319 return last_y;