GLHUI-1.0.0: c/HsGLWindow.c
#include "HsGLWindow.h"
static Display *display;
static Window window;
static GLXContext context;
static int width, height, scrwidth, scrheight;
static unsigned frame = 0;
static double ftime, dtime;
static int fullscreen = 0;
typedef struct
{
unsigned long flags;
unsigned long functions;
unsigned long decorations;
long inputMode;
unsigned long status;
} Hints;
void WindowSetFullscreen(int f)
{
XWindowChanges changes;
Hints hints;
Atom property = XInternAtom(display,"_MOTIF_WM_HINTS",True);
hints.flags = 2;
if(f)
{
hints.decorations = False;
changes.x = 0;
changes.y = 0;
changes.width = width = scrwidth;
changes.height = height = scrheight;
changes.stack_mode = Above;
fullscreen = 1;
}
else
{
hints.decorations = True;
changes.x = scrwidth/4;
changes.y = scrheight/4;
changes.width = width = scrwidth/2;
changes.height = height = scrheight/2;
changes.stack_mode = Above;
fullscreen = 0;
}
XChangeProperty(display, window, property, property, 32, PropModeReplace, (unsigned char *)&hints, 5);
XConfigureWindow(display, window, CWX | CWY | CWWidth | CWHeight | CWStackMode, &changes);
//XGrabKeyboard(display, window, True, GrabModeAsync, GrabModeAsync, CurrentTime);
//XGrabPointer(display, window, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, window, None, CurrentTime);
//XMapRaised(display, window);
}
int WindowInit(unsigned int const major, unsigned int const minor)
{
static const int glattr[] =
{
GLX_RENDER_TYPE, GLX_RGBA_BIT,
GLX_X_RENDERABLE, 1,
GLX_DOUBLEBUFFER, 1,
GLX_RED_SIZE, 8,
GLX_GREEN_SIZE, 8,
GLX_BLUE_SIZE, 8,
0
};
int gl3attr[] =
{
GLX_CONTEXT_MAJOR_VERSION_ARB, major,
GLX_CONTEXT_MINOR_VERSION_ARB, minor,
GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
0
};
if(!(display = XOpenDisplay(0)))
{
puts("Could not open display.\n");
return -1;
}
int nscreen = DefaultScreen(display);
scrwidth = XDisplayWidth(display, nscreen);
scrheight = XDisplayHeight(display, nscreen);
width = scrwidth / 2;
height = scrheight / 2;
static XVisualInfo *visual;
if(!(visual = glXChooseVisual(display, nscreen, (int*)glattr)))
{
puts("Could not find a visual.\n");
return -2;
}
int elemc;
GLXFBConfig *fbcfg = glXChooseFBConfig(display, nscreen, glattr, &elemc);
if(!fbcfg)
{
puts("Could not find FB config.\n");
return -3;
}
context = glXCreateContextAttribsARB(display, fbcfg[0], 0, 1, gl3attr);
Window root = RootWindow(display, visual->screen);
XSetWindowAttributes xattr;
xattr.event_mask = KeyPressMask | ButtonPressMask | StructureNotifyMask;
xattr.colormap = XCreateColormap(display, root, visual->visual, AllocNone);
window = XCreateWindow(display, root, 0, 0, width, height, 0, visual->depth, InputOutput, visual->visual, CWColormap | CWEventMask, &xattr);
XSetStandardProperties(display, window, "United Colors Of Funk", 0, None, 0, 0, 0);
XGrabKeyboard(display, window, True, GrabModeAsync, GrabModeAsync, CurrentTime);
XGrabPointer(display, window, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, window, None, CurrentTime);
XMapRaised(display, window);
glXMakeCurrent(display, window, context);
glViewport(0, 0, width, height);
XFree(fbcfg);
XFree(visual);
printf("OpenGL:\n\tvendor %s\n\trenderer %s\n\tversion %s\n\tshader language %s\n", glGetString(GL_VENDOR), glGetString(GL_RENDERER), glGetString(GL_VERSION), glGetString(GL_SHADING_LANGUAGE_VERSION));
return 1;
}
void WindowLoop(void (*Loop)())
{
struct timespec ts[3]; // even, odd, initial
int done = 0;
XEvent event;
clock_gettime(CLOCK_MONOTONIC, ts+2);
ts[0] = ts[1] = ts[2];
while(!done)
{
while(XPending(display) > 0)
{
XNextEvent(display, &event);
switch(event.type)
{
case ConfigureNotify:
if((event.xconfigure.width != width) || (event.xconfigure.height != height))
{
width = event.xconfigure.width;
height = event.xconfigure.height;
glViewport(0, 0, width, height);
}
break;
case ButtonPress:
done = 1;
break;
case KeyPress:
if(XLookupKeysym(&event.xkey, 0) == XK_Escape)
done = 1;
else if(XLookupKeysym(&event.xkey, 0) == XK_F1)
WindowSetFullscreen(!fullscreen);
break;
}
}
Loop();
glXSwapBuffers(display, window);
frame++;
clock_gettime(CLOCK_MONOTONIC, ts+(frame%2));
dtime = 1e-9*(ts[frame%2].tv_nsec - ts[!(frame%2)].tv_nsec) + (ts[frame%2].tv_sec - ts[!(frame%2)].tv_sec);
ftime = 1e-9*(ts[frame%2].tv_nsec - ts[2].tv_nsec) + (ts[frame%2].tv_sec - ts[2].tv_sec);
}
//WindowKill(0);
}
void WindowKill(const char *str)
{
puts(str);
if(context)
{
glXMakeCurrent(display, 0, 0);
glXDestroyContext(display, context);
context = 0;
}
XCloseDisplay(display);
}
unsigned WindowFrame(){ return frame; }
double WindowTime(){ return ftime; }
double WindowDTime(){ return dtime; }
unsigned WindowWidth(){ return width; }
unsigned WindowHeight(){ return height; }
unsigned WindowScrWidth(){ return scrwidth; }
unsigned WindowScrHeight(){ return scrheight; }