source: project/gl-display-glx/glx_display.c @ 3343

Last change on this file since 3343 was 3343, checked in by thu, 14 years ago

added autorepeat enabling/disabling

File size: 10.4 KB
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <math.h>
4
5#include <GL/glx.h>
6#include <X11/keysym.h>
7#include <X11/extensions/shape.h>
8
9#include <sys/time.h>
10
11#include "glx_display.h"
12
13
14#ifdef GLX_DISPLAY_SINGLESTATE
15 static gl_window_t _gl_window;
16 static gl_window_t * gl_window;
17#endif
18
19/* TODO clean file organization */
20void shape_window( gl_window_t  * gl_window, int width, int height );
21
22#ifdef GLX_DISPLAY_SINGLESTATE
23unsigned int
24get_width()
25{
26  return gl_window->width;
27}
28unsigned int
29get_height()
30{
31  return gl_window->height;
32}
33unsigned int
34get_screen_width()
35{
36  return gl_window->screen_width;
37}
38unsigned int
39get_screen_height()
40{
41  return gl_window->screen_height;
42}
43#else
44unsigned int
45get_width( gl_window_t  * gl_window )
46{
47  return gl_window->width;
48}
49unsigned int
50get_height( gl_window_t  * gl_window )
51{
52  return gl_window->height;
53}
54unsigned int
55get_screen_width( gl_window_t  * gl_window )
56{
57  return gl_window->screen_width;
58}
59unsigned int
60get_screen_height( gl_window_t  * gl_window )
61{
62  return gl_window->screen_height;
63}
64#endif
65 
66void
67enable_autorepeat (
68#ifndef GLX_DISPLAY_SINGLESTATE
69  gl_window_t  * gl_window
70#endif
71  )
72{
73  gl_window->autorepeat_flag = 1;
74}
75
76void
77disable_autorepeat (
78#ifndef GLX_DISPLAY_SINGLESTATE
79  gl_window_t  * gl_window
80#endif
81  )
82{
83  gl_window->autorepeat_flag = 0;
84}
85
86void
87destroy_gl_window (
88#ifndef GLX_DISPLAY_SINGLESTATE
89  gl_window_t  * gl_window
90#endif
91  )
92{
93  if ( gl_window->glx_context )
94  {
95    glXMakeCurrent( gl_window->display, None, NULL );
96    glXDestroyContext( gl_window->display, gl_window->glx_context );
97    gl_window->glx_context = NULL;
98  }
99  /* TODO */
100  glXDestroyWindow(gl_window->display, gl_window->glx_window);
101  XDestroyWindow(gl_window->display, gl_window->window);
102   /* if (GLWin.fs)
103    {
104        XF86VidModeSwitchToMode(GLWin.dpy, GLWin.screen, &GLWin.deskMode);
105        XF86VidModeSetViewPort(GLWin.dpy, GLWin.screen, 0, 0);
106    }*/
107
108  XCloseDisplay(gl_window->display);
109}
110
111/* local routines */
112int query_extensions_glx (Display * display);
113void exit_on_err (char * s);
114Cursor CreateNullPointer (void);
115void SetNullPointer (void);
116
117/*
118**
119*/
120
121#ifndef GLX_DISPLAY_SINGLESTATE
122  gl_window_t  *
123#else
124  void
125#endif
126create_gl_window (
127/*              const char * title, */
128                unsigned int width,
129                unsigned int height,
130                int double_buffered,
131                int fullscreen,
132                int no_border,
133                int use_shape_extension)
134{
135  int nelements;
136  GLXFBConfig * fbconfigs;
137  XVisualInfo * vi;
138 
139  int attrlist[] = {
140  /*  GLX_RGBA, */
141    GLX_DOUBLEBUFFER, double_buffered ? True : False,
142    GLX_RED_SIZE, 4,
143    GLX_GREEN_SIZE, 4,
144    GLX_BLUE_SIZE, 4,
145    GLX_DEPTH_SIZE, 16,
146    None };
147
148  XWindowAttributes root_attributes;
149
150#ifdef GLX_DISPLAY_SINGLESTATE
151  gl_window = & _gl_window;
152#else
153  gl_window_t  * gl_window = (gl_window_t *)malloc( sizeof(gl_window_t) );
154#endif
155
156  gl_window->width                = width;
157  gl_window->height               = height;
158  gl_window->double_buffered_flag = double_buffered;
159  gl_window->fullscreen_flag      = fullscreen;
160
161  gl_window->display = XOpenDisplay( NULL );
162  if( !gl_window->display )
163    exit_on_err(" XOpenDisplay failed.");
164 
165  gl_window->screen = DefaultScreen( gl_window->display );
166
167  /* TODO error handling */
168  XGetWindowAttributes( gl_window->display,
169                  RootWindow( gl_window->display,
170                              gl_window->screen ),
171                  &root_attributes);
172  gl_window->screen_width  = root_attributes.width;
173  gl_window->screen_height = root_attributes.height;
174
175  if ( fullscreen )
176  {
177    width  = gl_window->width  = gl_window->screen_width;
178    height = gl_window->height = gl_window->screen_height;
179  }
180
181  if( ! query_extensions_glx(gl_window->display) )
182    exit_on_err(" No supported glX extension.");
183
184  fbconfigs = glXChooseFBConfig( gl_window->display,
185                                 gl_window->screen,
186                                 attrlist,
187                                 &nelements );
188
189  vi = glXGetVisualFromFBConfig( gl_window->display, fbconfigs[0] );
190
191  gl_window->attributes.colormap = XCreateColormap( gl_window->display,
192                                   RootWindow( gl_window->display,
193                                               vi->screen ),
194                                   vi->visual, AllocNone);
195  gl_window->attributes.border_pixel = 0;
196  gl_window->attributes.background_pixel = 0;
197  gl_window->attributes.event_mask =
198    StructureNotifyMask | ExposureMask      |
199    KeyPressMask        | KeyReleaseMask    |
200    ButtonPressMask     | ButtonReleaseMask |
201    PointerMotionMask;
202  /* gl_window->attributes.override_redirect = 1; */
203
204  gl_window->window = XCreateWindow( gl_window->display,
205                       RootWindow( gl_window->display, vi->screen ),
206                      (1280-width)/2,(800-height)/2, width,height , 0,
207                      vi->depth, InputOutput, vi->visual,
208
209                      CWBorderPixel | CWBackPixel |
210                      CWColormap | CWEventMask /*| CWOverrideRedirect*/,
211
212                      &gl_window->attributes);
213  /* FIXME handle this ?*/
214  if ( !fullscreen && no_border )
215  {
216    shape_window( gl_window, width, height );
217  }
218
219  gl_window->glx_window = glXCreateWindow( gl_window->display, fbconfigs[0], gl_window->window, 0);
220
221  gl_window->glx_context = glXCreateNewContext( gl_window->display, fbconfigs[0],
222                           GLX_RGBA_TYPE, 0, GL_TRUE);
223
224  glXMakeContextCurrent( gl_window->display, gl_window->glx_window, gl_window->glx_window, gl_window->glx_context);
225
226  XMapWindow(gl_window->display, gl_window->window);
227  for (;;)
228  {
229    XEvent e;
230    XNextEvent( gl_window->display, &e );
231    if ( e.type == MapNotify ) break;
232  }
233
234  /* TODO provide the following to scheme side
235  if( glXIsDirect(gl_window->display, gl_window->glx_context) )
236    printf(" Direct Rendering.\n");
237  else
238    printf(" No Direct Rendering.\n");
239  */
240
241  XFree(fbconfigs);
242  XFree(vi);
243 
244#ifndef GLX_DISPLAY_SINGLESTATE
245  return gl_window;
246#endif
247}
248
249void
250grab_keyboard(
251#ifndef GLX_DISPLAY_SINGLESTATE
252  gl_window_t  * gl_window
253#endif
254  )
255{
256  XGrabKeyboard(gl_window->display, gl_window->window, True,
257                  GrabModeAsync, GrabModeAsync, CurrentTime); 
258}
259
260void
261grab_mouse(
262#ifndef GLX_DISPLAY_SINGLESTATE
263  gl_window_t  * gl_window
264#endif
265  )
266{
267  XGrabPointer(gl_window->display, gl_window->window, True, ButtonPressMask,
268                  GrabModeAsync, GrabModeAsync,
269                  gl_window->window, None, CurrentTime);
270}
271
272void
273warp_mouse(
274#ifndef GLX_DISPLAY_SINGLESTATE
275  gl_window_t  * gl_window,
276#endif
277  int x, int y
278  )
279{
280  XWarpPointer( gl_window->display, None, gl_window->window, 0,0,0,0,
281               /* gl_window->screen_width/2 , gl_window->screen_height/2 ); */
282                  x , y );
283}
284
285
286void
287swap_buffers (
288#ifndef GLX_DISPLAY_SINGLESTATE
289  gl_window_t  * gl_window
290#endif
291  )
292{
293  if ( gl_window->double_buffered_flag )
294  {
295    glXSwapBuffers( gl_window->display, gl_window->glx_window );
296  }
297  else
298  {
299    glFlush();
300  }
301}
302
303int event_type( XEvent * e ) { return e->type; }
304int event_x( XButtonEvent * e ) { return e->x; }
305int event_y( XButtonEvent * e ) { return e->y; }
306int event_button( XButtonEvent * e ) { return e->button; }
307int event_keycode( XEvent * e ) { return XLookupKeysym( &e->xkey, 0 ); }
308
309/*
310 * Returns a (pointer to a) XEvent.
311 * The type of the event could be LASTEvent + 1 if there's no actual event.
312 */
313XEvent *
314receive_event (
315#ifndef GLX_DISPLAY_SINGLESTATE
316  gl_window_t  * gl_window
317#endif
318  )
319{
320  static XEvent e;
321  static int pending = 0;
322  int repeating = 1;
323
324  if ( pending == 0 ) pending = XPending( gl_window->display );
325  while ( pending > 0 && repeating )
326  {
327    repeating = 0;
328    XNextEvent( gl_window->display, &e );
329    pending--;
330
331    /* Handle autorepeat.
332     * The mechanic is taken from Quake3.
333     * In Quake3, they assume the KeyRelease and
334     * the followinf KeyPress have the same time.
335     * Here, I've added a delta of 10 because
336     * I experienced different times for
337     * autorepeating events (actually, it was only
338     * a delta of 1 millisecond...).
339     */
340    if ( e.type == KeyRelease && !gl_window->autorepeat_flag )
341    {
342      if ( pending == 0 ) pending = XPending( gl_window->display );
343      if ( pending > 0 )
344      {
345        XEvent peekevent;
346        XPeekEvent( gl_window->display, &peekevent );
347        if ((peekevent.type == KeyPress) &&
348            (peekevent.xkey.keycode == e.xkey.keycode) &&
349            (peekevent.xkey.time >= e.xkey.time &&
350             peekevent.xkey.time <= e.xkey.time + 10))
351        {
352          /* it's autorepeating, remove the KeyPress. */
353          XNextEvent( gl_window->display, &e );
354          pending--;
355          repeating = 1;
356        }
357      }
358    }
359  }
360 
361  if ( repeating )
362  {
363    e.type = LASTEvent + 1; /* means 'no event' */
364  }
365
366  return (void *) &e;
367}
368
369/*
370** local routines
371*/
372int query_extensions_glx(Display * dpy)
373{
374  int major, minor;
375
376
377  if(! glXQueryExtension(dpy, NULL, NULL))
378    return 0;
379
380  glXQueryVersion(dpy, &major, &minor);
381  if( (major == 1) && (minor < 3) )
382    {
383      printf(" glX version unsupported : less than 1.3\n");
384      return 0;
385    }
386
387  /* provide to scheme side
388  printf(" glX vendor     : %s\n",
389         glXGetClientString(dpy, GLX_VENDOR) );
390  printf(" glX version    : %s\n",
391         glXGetClientString(dpy, GLX_VERSION) );
392  printf(" glX extensions : %s\n",
393         glXGetClientString(dpy, GLX_EXTENSIONS) );
394  */
395
396  return 1;
397
398}
399
400void exit_on_err(char * s)
401{
402  fprintf(stderr, "%s\n", s);
403  exit(1);
404}
405
406
407void
408shape_window( gl_window_t  * gl_window, int width, int height )
409{
410  XRectangle rectangles[3];
411  int n_rectangles = 3;
412
413  rectangles[0].x = 1;
414  rectangles[0].y = 0;
415  rectangles[0].width = width - 2;
416  rectangles[0].height = 1;
417 
418  rectangles[1].x = 0;
419  rectangles[1].y = 1;
420  rectangles[1].width = width;
421  rectangles[1].height = height - 2;
422  rectangles[2].x = 1;
423  rectangles[2].y = height - 1;
424  rectangles[2].width = width - 2;
425  rectangles[2].height = 1;
426
427  XShapeCombineRectangles(gl_window->display, gl_window->window, ShapeBounding, 0, 0,
428                  rectangles, n_rectangles, ShapeSet, 0);
429}
430
431/*
432Cursor CreateNullPointer(void)
433{
434  Cursor cursor;
435  Pixmap pm;
436  GC ctx;
437  XGCValues val;
438  XColor color;
439
440  pm = XCreatePixmap(dpy, RootWindow(dpy, scrnum), 1, 1, 1);
441  val.function = GXclear;
442  ctx = XCreateGC(dpy, pm, GCFunction, &val);
443
444  color.pixel = 0;
445  color.red = 0;
446  color.flags = 04;
447  cursor = XCreatePixmapCursor(dpy, pm, pm, &color, &color, 0,0);
448
449  XFreePixmap(dpy, pm);
450  XFreeGC(dpy, ctx);
451
452  return cursor;
453}
454
455void SetNullPointer(void)
456{
457  XDefineCursor( dpy, win, CreateNullPointer() );
458}*/
459
460
461
462
463
464int time_milliseconds( void )
465{
466  static unsigned long time_base = 0;
467  struct timeval tp;
468 
469  gettimeofday (&tp, NULL);
470  if ( !time_base )
471  {
472    time_base = tp.tv_sec;
473    return tp.tv_usec / 1000;
474  }
475
476  int current = (tp.tv_sec - time_base)*1000 + tp.tv_usec/1000;
477  return current;
478}
479
480
Note: See TracBrowser for help on using the repository browser.