661 lines
17 KiB
C
661 lines
17 KiB
C
/*
|
|
Raydium - CQFD Corp.
|
|
http://raydium.org/
|
|
License: GPL - GNU General Public License, see "gpl.txt" file.
|
|
*/
|
|
|
|
#include "headers/myglut.h"
|
|
|
|
#include <X11/Xlib.h>
|
|
#include <X11/Xatom.h>
|
|
#include <X11/keysym.h>
|
|
#include <X11/cursorfont.h>
|
|
#include <X11/Xlib.h>
|
|
#include <X11/Xatom.h>
|
|
//#include <X11/Xutil.h> // provided by glx
|
|
|
|
#include <GL/glx.h>
|
|
|
|
#ifdef HAVE_XINERAMA
|
|
#include <X11/extensions/Xinerama.h>
|
|
#endif
|
|
|
|
#ifdef HAVE_MOTIF
|
|
#include <X11/Xm/MwmUtil.h>
|
|
#else
|
|
/* bit definitions for MwmHints.flags */
|
|
#define MWM_HINTS_FUNCTIONS (1L << 0)
|
|
#define MWM_HINTS_DECORATIONS (1L << 1)
|
|
#define MWM_HINTS_INPUT_MODE (1L << 2)
|
|
#define MWM_HINTS_STATUS (1L << 3)
|
|
|
|
/* bit definitions for MwmHints.decorations */
|
|
#define MWM_DECOR_ALL (1L << 0)
|
|
#define MWM_DECOR_BORDER (1L << 1)
|
|
#define MWM_DECOR_RESIZEH (1L << 2)
|
|
#define MWM_DECOR_TITLE (1L << 3)
|
|
#define MWM_DECOR_MENU (1L << 4)
|
|
#define MWM_DECOR_MINIMIZE (1L << 5)
|
|
#define MWM_DECOR_MAXIMIZE (1L << 6)
|
|
|
|
typedef struct
|
|
{
|
|
unsigned long flags ;
|
|
unsigned long functions ;
|
|
unsigned long decorations ;
|
|
long inputMode ;
|
|
unsigned long status ;
|
|
} PropMotifWmHints ;
|
|
|
|
#define PROP_MOTIF_WM_HINTS_ELEMENTS 5
|
|
|
|
#endif
|
|
|
|
#ifndef GLX_SAMPLE_BUFFERS_ARB
|
|
#define GLX_SAMPLE_BUFFERS_ARB 100000
|
|
#define GLX_SAMPLES_ARB 100001
|
|
#endif
|
|
|
|
|
|
Display *currDisplay ;
|
|
XVisualInfo *visualInfo ;
|
|
Window currHandle ;
|
|
GLXContext currContext ;
|
|
Window rootWindow ;
|
|
Atom delWinAtom ;
|
|
|
|
int currScreen;
|
|
int currConnect;
|
|
|
|
typedef struct PixelFormat
|
|
{
|
|
int num_samples ;
|
|
int bits_per_pixel ;
|
|
int z_bits ;
|
|
int stencil_bits ;
|
|
} PixelFormat;
|
|
|
|
signed char XineramaAndFullscreenFocusHack=0;
|
|
signed char FullscreenFlag=0;
|
|
|
|
PixelFormat preferred_pixel_formats [] =
|
|
{
|
|
/* NumSamples, RGB_bits, Z_bits, Stencil */
|
|
|
|
{ 0, 24, 24, 1 }, /* Progressively nastier image formats */
|
|
{ 0, 16, 24, 1 },
|
|
{ 0, 16, 16, 1 },
|
|
{ 0, 16, 16, 0 },
|
|
{ -1, -1, -1, -1 } /* Magic end marker */
|
|
} ;
|
|
|
|
void pwInit ( int x, int y, int w, int h, int multisample,
|
|
char *title, int border, int num_samples );
|
|
int raydium_init_cli_option(char *option, char *value);
|
|
|
|
|
|
// ---------------------- public API
|
|
|
|
void glutInit(int *argc, char **argv)
|
|
{
|
|
currDisplay = NULL ;
|
|
visualInfo = NULL ;
|
|
|
|
currScreen = 0;
|
|
currConnect = 0;
|
|
|
|
glutReshapeFuncCB=NULL;
|
|
glutKeyboardFuncCB=NULL;
|
|
glutSpecialUpFuncCB=NULL;
|
|
glutSpecialFuncCB=NULL;
|
|
glutMotionFuncCB=NULL;
|
|
glutPassiveMotionFuncCB=NULL;
|
|
glutMouseFuncCB=NULL;
|
|
glutDisplayFuncCB=NULL;
|
|
glutIdleFuncCB=NULL;
|
|
|
|
_glutMouseVisible=1;
|
|
}
|
|
|
|
|
|
|
|
|
|
void mylgutCloseWindow(void)
|
|
{
|
|
glXDestroyContext ( currDisplay, currContext ) ;
|
|
XDestroyWindow ( currDisplay, currHandle ) ;
|
|
XFlush ( currDisplay ) ;
|
|
}
|
|
|
|
|
|
|
|
//glutSetCursor
|
|
void glutSetCursor(int cursor)
|
|
{
|
|
int currCursor;
|
|
Pixmap pix ;
|
|
char blank_cursor[16*16];
|
|
XColor bcol = { 0 } ;
|
|
|
|
switch(cursor)
|
|
{
|
|
case GLUT_CURSOR_LEFT_ARROW:
|
|
currCursor = XC_left_ptr;
|
|
XDefineCursor( currDisplay, currHandle,
|
|
XCreateFontCursor ( currDisplay, currCursor ) ) ;
|
|
_glutMouseVisible=1;
|
|
break;
|
|
case GLUT_CURSOR_NONE:
|
|
default:
|
|
memset(blank_cursor,0,16*16);
|
|
|
|
pix = XCreateBitmapFromData ( currDisplay,
|
|
rootWindow,
|
|
blank_cursor, 16, 16 ) ;
|
|
XDefineCursor ( currDisplay, currHandle,
|
|
XCreatePixmapCursor ( currDisplay,
|
|
pix, pix, &bcol, &bcol, 0, 0 ) ) ;
|
|
XFreePixmap ( currDisplay, pix ) ;
|
|
_glutMouseVisible=1;
|
|
}
|
|
}
|
|
|
|
//glutWarpPointer (move mouse)
|
|
void glutWarpPointer(int x, int y)
|
|
{
|
|
XWarpPointer(currDisplay, None, currHandle, 0, 0, 0, 0, x, y);
|
|
XFlush(currDisplay);
|
|
}
|
|
|
|
//glutSwapBuffers
|
|
void glutSwapBuffers(void)
|
|
{
|
|
glFlush () ;
|
|
glXSwapBuffers ( currDisplay, currHandle ) ;
|
|
// get events ?
|
|
}
|
|
|
|
|
|
//glutMainLoop is generic (myglut.c)
|
|
|
|
// ------------- private part
|
|
|
|
void chooseVisual (PixelFormat *pf)
|
|
{
|
|
int attribs [ 100 ] ;
|
|
int n = 0 ;
|
|
|
|
attribs [n++] = GLX_RGBA ;
|
|
|
|
switch ( pf->bits_per_pixel )
|
|
{
|
|
case 3 :
|
|
attribs [n++] = GLX_RED_SIZE ; attribs [n++] = 1 ;
|
|
attribs [n++] = GLX_GREEN_SIZE ; attribs [n++] = 1 ;
|
|
attribs [n++] = GLX_BLUE_SIZE ; attribs [n++] = 1 ;
|
|
break ;
|
|
|
|
case 16 :
|
|
attribs [n++] = GLX_RED_SIZE ; attribs [n++] = 5 ;
|
|
attribs [n++] = GLX_GREEN_SIZE ; attribs [n++] = 6 ;
|
|
attribs [n++] = GLX_BLUE_SIZE ; attribs [n++] = 5 ;
|
|
break ;
|
|
|
|
case 24 :
|
|
attribs [n++] = GLX_RED_SIZE ; attribs [n++] = 8 ;
|
|
attribs [n++] = GLX_GREEN_SIZE ; attribs [n++] = 8 ;
|
|
attribs [n++] = GLX_BLUE_SIZE ; attribs [n++] = 8 ;
|
|
break ;
|
|
}
|
|
|
|
switch ( pf->z_bits )
|
|
{
|
|
case 1 : attribs [n++] = GLX_DEPTH_SIZE ; attribs [n++] = 1 ; break ;
|
|
case 16 : attribs [n++] = GLX_DEPTH_SIZE ; attribs [n++] = 16 ; break ;
|
|
case 24 : attribs [n++] = GLX_DEPTH_SIZE ; attribs [n++] = 24 ; break ;
|
|
case 32 : attribs [n++] = GLX_DEPTH_SIZE ; attribs [n++] = 32 ; break ;
|
|
}
|
|
|
|
switch ( pf->stencil_bits )
|
|
{
|
|
case 1 : attribs [n++] = GLX_STENCIL_SIZE ; attribs [n++] = 1 ; break ;
|
|
case 8 : attribs [n++] = GLX_STENCIL_SIZE ; attribs [n++] = 8 ; break ;
|
|
}
|
|
|
|
if ( pf->num_samples > 0 )
|
|
{
|
|
attribs [n++] = GLX_SAMPLE_BUFFERS_ARB ; attribs [n++] = 1 ;
|
|
attribs [n++] = GLX_SAMPLES_ARB ; attribs [n++] = pf->num_samples ;
|
|
}
|
|
|
|
attribs [n++] = GLX_DOUBLEBUFFER ;
|
|
attribs [n++] = None ;
|
|
|
|
visualInfo = glXChooseVisual ( currDisplay, currScreen, attribs ) ;
|
|
}
|
|
|
|
|
|
|
|
void pwInit ( int x, int y, int w, int h, int multisample,
|
|
char *title, int border, int num_samples )
|
|
{
|
|
char *displayName = NULL;
|
|
int i;
|
|
int origin[2];
|
|
int size[2];
|
|
int DispX,DispY; // X screen size
|
|
|
|
XSetWindowAttributes attribs ;
|
|
XTextProperty textProperty ;
|
|
XSizeHints sizeHints ;
|
|
XWMHints wmHints ;
|
|
unsigned int mask ;
|
|
PixelFormat pf ;
|
|
|
|
#ifdef HAVE_XINERAMA
|
|
int i_d1, i_d2;
|
|
#endif
|
|
|
|
PropMotifWmHints hints ;
|
|
Atom prop_t ;
|
|
Atom prop ;
|
|
|
|
displayName=getenv ( "DISPLAY" ) ;
|
|
|
|
if ( displayName == NULL ) displayName = ":0.0" ;
|
|
|
|
currDisplay = XOpenDisplay ( displayName ) ;
|
|
|
|
if ( currDisplay == NULL )
|
|
{
|
|
raydium_log("(my)glut: ERROR: Can't open display '%s'",
|
|
XDisplayName ( displayName ) ) ;
|
|
exit ( 1 ) ;
|
|
}
|
|
|
|
/* OpenGL GLX extension availability? */
|
|
|
|
if ( ! glXQueryExtension ( currDisplay, NULL, NULL ) )
|
|
{
|
|
raydium_log("(my)glut: ERROR: GLX extension not available on display '%s'",
|
|
XDisplayName ( displayName ) ) ;
|
|
exit ( 1 ) ;
|
|
}
|
|
|
|
currScreen = DefaultScreen ( currDisplay ) ;
|
|
rootWindow = RootWindow ( currDisplay, currScreen ) ;
|
|
currConnect = ConnectionNumber ( currDisplay ) ;
|
|
delWinAtom = XInternAtom ( currDisplay, "WM_DELETE_WINDOW", 0 ) ;
|
|
|
|
DispX = DisplayWidth ( currDisplay, currScreen ) ;
|
|
DispY = DisplayHeight ( currDisplay, currScreen ) ;
|
|
|
|
#ifdef HAVE_XINERAMA
|
|
if(XineramaQueryExtension( currDisplay, &i_d1, &i_d2 )
|
|
&& XineramaIsActive( currDisplay ) )
|
|
{
|
|
XineramaScreenInfo *screens;
|
|
int num_screens;
|
|
int selected;
|
|
char str[RAYDIUM_MAX_NAME_LEN];
|
|
|
|
|
|
screens = XineramaQueryScreens(currDisplay,&num_screens);
|
|
raydium_log("Xinerama detected with %i screens:",num_screens);
|
|
|
|
for(i=0;i<num_screens;i++)
|
|
{
|
|
raydium_log("*** screen %i : %ix%i at (%i,%i)",i,screens[i].width,screens[i].height,screens[i].x_org,screens[i].y_org);
|
|
}
|
|
|
|
if(raydium_init_cli_option("xinerama-fullscreen",NULL))
|
|
{
|
|
raydium_log("... but using Xinerama fullscreen anyway !");
|
|
}
|
|
else
|
|
{
|
|
if(raydium_init_cli_option("xinerama-screen",str))
|
|
selected=atoi(str);
|
|
else
|
|
selected=0;
|
|
|
|
if(selected<0 || selected >=num_screens)
|
|
{
|
|
raydium_log("invalid screen id !");
|
|
selected=0;
|
|
}
|
|
raydium_log("using Xinerama screen %i",selected);
|
|
|
|
x+=screens[selected].x_org;
|
|
y+=screens[selected].y_org;
|
|
DispX=screens[selected].width;
|
|
DispY=screens[selected].height;
|
|
if(w==-1 && h==-1) XineramaAndFullscreenFocusHack=1;
|
|
}
|
|
|
|
XFree(screens);
|
|
} // end Xinerama
|
|
else
|
|
{
|
|
raydium_log("no Xinerama on this display");
|
|
}
|
|
#else
|
|
raydium_log("no Xinerama support. See config.h for HAVE_XINERAMA symbol");
|
|
#endif
|
|
|
|
if ( w == -1 && h == -1)
|
|
{
|
|
w = DispX;
|
|
h = DispY;
|
|
FullscreenFlag = 1;
|
|
}
|
|
|
|
origin [ 0 ] = x ;
|
|
origin [ 1 ] = y ;
|
|
size [ 0 ] = w ;
|
|
size [ 1 ] = h ;
|
|
|
|
for (i = 0 ; preferred_pixel_formats [ i ] . num_samples >= 0 ; i++ )
|
|
{
|
|
pf = preferred_pixel_formats [ i ] ;
|
|
pf . num_samples = num_samples ;
|
|
|
|
chooseVisual ( &pf ) ;
|
|
|
|
if ( visualInfo != NULL )
|
|
break ;
|
|
}
|
|
|
|
if ( visualInfo == NULL )
|
|
{
|
|
num_samples = 0 ;
|
|
|
|
for (i = 0 ; preferred_pixel_formats [ i ] . num_samples >= 0 ; i++ )
|
|
{
|
|
pf = preferred_pixel_formats [ i ] ;
|
|
pf . num_samples = num_samples ;
|
|
|
|
chooseVisual ( &pf ) ;
|
|
|
|
if ( visualInfo != NULL )
|
|
break ;
|
|
}
|
|
|
|
if ( visualInfo == NULL )
|
|
{
|
|
raydium_log("(my)glut: ERROR: Unable to open a suitable window");
|
|
exit ( 1 ) ;
|
|
}
|
|
}
|
|
|
|
|
|
attribs.event_mask = StructureNotifyMask | ExposureMask |
|
|
ButtonPressMask | ButtonReleaseMask |
|
|
KeyPressMask | KeyReleaseMask |
|
|
EnterWindowMask | LeaveWindowMask |
|
|
PointerMotionMask | ButtonMotionMask |
|
|
VisibilityChangeMask ;
|
|
|
|
attribs.background_pixmap = None ;
|
|
attribs.background_pixel = 0 ;
|
|
attribs.border_pixel = 0 ;
|
|
|
|
attribs.colormap = XCreateColormap ( currDisplay, rootWindow,
|
|
visualInfo->visual, AllocNone ) ;
|
|
|
|
mask = CWBackPixmap | CWBorderPixel | CWColormap | CWEventMask;
|
|
|
|
if(FullscreenFlag)
|
|
{
|
|
attribs.override_redirect = True;
|
|
mask |= CWOverrideRedirect;
|
|
}
|
|
|
|
currHandle = XCreateWindow ( currDisplay, rootWindow,
|
|
x, y, w, h, 0, visualInfo->depth,
|
|
InputOutput, visualInfo->visual,
|
|
mask, &attribs ) ;
|
|
|
|
currContext = glXCreateContext ( currDisplay, visualInfo, NULL, 1 ) ;
|
|
|
|
glXMakeCurrent ( currDisplay, currHandle, currContext ) ;
|
|
|
|
if ( ! glXIsDirect ( currDisplay, glXGetCurrentContext() ) )
|
|
{
|
|
raydium_log("(my)glut: WARNING: This is an *INDIRECT* rendering context.") ;
|
|
}
|
|
|
|
sizeHints.flags = 0 ;
|
|
|
|
if ( x >= 0 && y >= 0 )
|
|
sizeHints.flags |= USPosition ;
|
|
|
|
sizeHints.flags |= USSize ;
|
|
|
|
sizeHints.x = x ; sizeHints.y = y ;
|
|
sizeHints.width = w ; sizeHints.height = h ;
|
|
|
|
if(FullscreenFlag)
|
|
{
|
|
// make this window unresizable
|
|
sizeHints.flags |= PMinSize;
|
|
sizeHints.flags |= PMaxSize;
|
|
sizeHints.min_width=w;
|
|
sizeHints.max_width=w;
|
|
sizeHints.min_height=h;
|
|
sizeHints.max_height=h;
|
|
}
|
|
|
|
|
|
wmHints.flags = StateHint;
|
|
wmHints.initial_state = NormalState ;
|
|
|
|
|
|
hints . flags = MWM_HINTS_DECORATIONS ;
|
|
hints . decorations = border ? MWM_DECOR_ALL : 0 ;
|
|
|
|
prop_t = prop = XInternAtom ( currDisplay, "_MOTIF_WM_HINTS", True ) ;
|
|
|
|
if ( prop != 0 )
|
|
XChangeProperty ( currDisplay, currHandle, prop, prop_t, 32,
|
|
PropModeReplace, (unsigned char *) &hints,
|
|
PROP_MOTIF_WM_HINTS_ELEMENTS) ;
|
|
|
|
XStringListToTextProperty ( (char **) &title, 1, &textProperty ) ;
|
|
|
|
XSetWMProperties ( currDisplay, currHandle,
|
|
&textProperty, &textProperty, 0, 0,
|
|
&sizeHints, &wmHints, NULL ) ;
|
|
XSetWMProtocols ( currDisplay, currHandle, &delWinAtom , 1 );
|
|
XMapWindow ( currDisplay, currHandle ) ;
|
|
glXMakeCurrent ( currDisplay, currHandle, currContext ) ;
|
|
|
|
glutSetCursor(GLUT_CURSOR_LEFT_ARROW);
|
|
|
|
|
|
glClear ( GL_COLOR_BUFFER_BIT ) ;
|
|
glutSwapBuffers();
|
|
glClear ( GL_COLOR_BUFFER_BIT ) ;
|
|
glutSwapBuffers();
|
|
|
|
raydium_log("Found %ix%i with %i bpp color and %i bits zbuffer (stencil is %i)",sizeHints.width,sizeHints.height,pf.bits_per_pixel,pf.z_bits,pf.stencil_bits);
|
|
|
|
_glutWindowSize[0]=sizeHints.width;
|
|
_glutWindowSize[1]=sizeHints.height;
|
|
|
|
if(FullscreenFlag)
|
|
XGrabKeyboard(currDisplay,currHandle,False,GrabModeAsync,GrabModeAsync,CurrentTime);
|
|
// XSetInputFocus(currDisplay,currHandle,RevertToNone,CurrentTime);
|
|
}
|
|
|
|
|
|
void myglutGetEvents (void)
|
|
{
|
|
static int size[2]={-1,-1};
|
|
XEvent event ;
|
|
|
|
XComposeStatus composeStatus ;
|
|
char asciiCode [ 32 ] ;
|
|
KeySym keySym ;
|
|
|
|
int len,result;
|
|
signed char special=0;
|
|
|
|
// insideCallback = true ;
|
|
|
|
while ( XPending ( currDisplay ) )
|
|
{
|
|
int updown = GLUT_DOWN ;
|
|
|
|
XNextEvent ( currDisplay, &event ) ;
|
|
|
|
// refreshModifiers ( &event ) ;
|
|
|
|
switch ( event.type )
|
|
{
|
|
case ClientMessage : exit(0) ; break ;
|
|
case DestroyNotify : exit(0) ; break ;
|
|
|
|
case ConfigureNotify :
|
|
if ( currHandle == event.xconfigure.window &&
|
|
( size[0] != event.xconfigure.width ||
|
|
size[1] != event.xconfigure.height ) )
|
|
{
|
|
size[0] = event.xconfigure.width ;
|
|
size[1] = event.xconfigure.height ;
|
|
|
|
glXMakeCurrent ( currDisplay, currHandle, currContext ) ;
|
|
glXWaitX () ;
|
|
|
|
if (glutReshapeFuncCB)
|
|
glutReshapeFuncCB(size[0], size[1]);
|
|
}
|
|
break;
|
|
|
|
case MappingNotify:
|
|
XRefreshKeyboardMapping ( (XMappingEvent *) &event ) ;
|
|
break;
|
|
|
|
case EnterNotify :
|
|
if(XineramaAndFullscreenFocusHack)
|
|
{
|
|
XSetInputFocus(currDisplay,currHandle,RevertToParent,CurrentTime);
|
|
XRaiseWindow(currDisplay,currHandle);
|
|
}
|
|
break;
|
|
case LeaveNotify :
|
|
case VisibilityNotify:
|
|
case Expose : break ;
|
|
|
|
case MotionNotify :
|
|
if (glutPassiveMotionFuncCB)
|
|
glutPassiveMotionFuncCB( event.xmotion.x, event.xmotion.y);
|
|
break ;
|
|
|
|
case ButtonRelease :
|
|
updown = GLUT_UP ;
|
|
// FALLTHROUGH
|
|
|
|
case ButtonPress :
|
|
{
|
|
if (glutMouseFuncCB)
|
|
glutMouseFuncCB(event.xbutton.button-1, updown, event.xbutton.x, event.xbutton.y ) ;
|
|
}
|
|
break ;
|
|
|
|
case KeyRelease :
|
|
updown = GLUT_UP ;
|
|
// FALLTHROUGH
|
|
|
|
case KeyPress :
|
|
|
|
len = XLookupString( &event.xkey, asciiCode, sizeof(asciiCode),
|
|
&keySym, &composeStatus ) ;
|
|
result = -1 ;
|
|
|
|
if( len > 0 )
|
|
result = asciiCode[ 0 ] ;
|
|
else
|
|
{
|
|
special=1;
|
|
switch( keySym )
|
|
{
|
|
case XK_F1: result = GLUT_KEY_F1; break;
|
|
case XK_F2: result = GLUT_KEY_F2; break;
|
|
case XK_F3: result = GLUT_KEY_F3; break;
|
|
case XK_F4: result = GLUT_KEY_F4; break;
|
|
case XK_F5: result = GLUT_KEY_F5; break;
|
|
case XK_F6: result = GLUT_KEY_F6; break;
|
|
case XK_F7: result = GLUT_KEY_F7; break;
|
|
case XK_F8: result = GLUT_KEY_F8; break;
|
|
case XK_F9: result = GLUT_KEY_F9; break;
|
|
case XK_F10: result = GLUT_KEY_F10; break;
|
|
case XK_F11: result = GLUT_KEY_F11; break;
|
|
case XK_F12: result = GLUT_KEY_F12; break;
|
|
|
|
case XK_KP_Left:
|
|
case XK_Left: result = GLUT_KEY_LEFT; break;
|
|
|
|
case XK_KP_Right:
|
|
case XK_Right: result = GLUT_KEY_RIGHT; break;
|
|
|
|
case XK_KP_Up:
|
|
case XK_Up: result = GLUT_KEY_UP; break;
|
|
|
|
case XK_KP_Down:
|
|
case XK_Down: result = GLUT_KEY_DOWN; break;
|
|
|
|
case XK_KP_Prior:
|
|
case XK_Prior: result = GLUT_KEY_PAGE_UP; break;
|
|
case XK_KP_Next:
|
|
case XK_Next: result = GLUT_KEY_PAGE_DOWN; break;
|
|
case XK_KP_Home:
|
|
case XK_Home: result = GLUT_KEY_HOME; break;
|
|
case XK_KP_End:
|
|
case XK_End: result = GLUT_KEY_END; break;
|
|
case XK_KP_Insert:
|
|
case XK_Insert: result = GLUT_KEY_INSERT; break;
|
|
}
|
|
}
|
|
|
|
if(result!=-1)
|
|
{
|
|
// check autorepeat with current KeyRelease and next event
|
|
if (special && XEventsQueued(currDisplay, QueuedAfterReading))
|
|
{
|
|
XEvent ahead;
|
|
XPeekEvent(currDisplay, &ahead);
|
|
if (ahead.type == KeyPress && event.type == KeyRelease
|
|
&& ahead.xkey.window == event.xkey.window
|
|
&& ahead.xkey.keycode == event.xkey.keycode
|
|
&& ahead.xkey.time == event.xkey.time)
|
|
{
|
|
// repeating key. Discard event.
|
|
break;
|
|
}
|
|
}
|
|
|
|
// special down
|
|
if(special && updown==GLUT_DOWN && glutSpecialFuncCB && !raydium_key[result])
|
|
glutSpecialFuncCB(result,event.xkey.x, event.xkey.y);
|
|
|
|
// special up
|
|
if(special && updown==GLUT_UP && glutSpecialUpFuncCB && raydium_key[result])
|
|
glutSpecialUpFuncCB(result,event.xkey.x, event.xkey.y);
|
|
|
|
// normal
|
|
if(!special && updown==GLUT_DOWN && glutKeyboardFuncCB)
|
|
glutKeyboardFuncCB(result,event.xkey.x, event.xkey.y);
|
|
|
|
}
|
|
|
|
break ;
|
|
}
|
|
}
|
|
|
|
// insideCallback = false ;
|
|
|
|
glXMakeCurrent ( currDisplay, currHandle, currContext ) ;
|
|
}
|
|
|