/*
 * Credit to:
 * Compiled with:
 *
 * Modified (to emphasise simularities with Win32) - GLJ 18/12/2014
 */

#include<stdio.h>
#include<stdlib.h>
#include<X11/X.h>
#include<X11/Xlib.h>
#include<GL/gl.h>
#include<GL/glx.h>
#include<GL/glu.h>

Display                 *dpy;
Window                  root;
GLint                   att[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None };
XVisualInfo             *vi;
Colormap                cmap;
XSetWindowAttributes    swa;
Window                  win;
GLXContext              glc;
XWindowAttributes       gwa;
XEvent                  xev;

void Draw() 
{
    glClearColor(1.0, 1.0, 1.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-1., 1., -1., 1., 1., 20.);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(0., 0., 10., 0., 0., 0., 0., 1., 0.);

    glBegin(GL_QUADS);
        glColor3f(1., 0., 0.); glVertex3f(-.75, -.75, 0.);
        glColor3f(0., 1., 0.); glVertex3f( .75, -.75, 0.);
        glColor3f(0., 0., 1.); glVertex3f( .75,  .75, 0.);
        glColor3f(1., 1., 0.); glVertex3f(-.75,  .75, 0.);
    glEnd();
} 

void makeWindow()
{
    /* Argument is NULL - display is on this computer */
    dpy = XOpenDisplay(NULL);
 
    if(dpy == NULL) 
    {
        printf("\n\tcannot connect to X server\n\n");
        exit(0);
    }

    /* Get a handle to root window - desktop */
    root = DefaultRootWindow(dpy);

    /* Select visual properties the window based on attr 
     * GLint                   att[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None };
     */
    vi = glXChooseVisual(dpy, 0, att);

    if(vi == NULL) 
    {
        printf("\n\tno appropriate visual found\n\n");
        exit(0);
    } 
    else 
    {
        printf("\n\tvisual %p selected\n", (void *)vi->visualid); 
        /* %p creates hexadecimal output like in glxinfo */
    }


    /* Create a colour map */
    cmap = XCreateColormap(dpy, root, vi->visual, AllocNone);

    /* Set the windows colour map and event mask */
    swa.colormap = cmap;
    swa.event_mask = ExposureMask | KeyPressMask;

    /* Create the window */
    win = XCreateWindow(dpy, root, 0, 0, 600, 600, 0, vi->depth, InputOutput, vi->visual, CWColormap | CWEventMask, &swa);

    /* Make the window appear, win is just a window id (long int) */
    XMapWindow(dpy, win);

    /* Change window name */
    XStoreName(dpy, win, "VERY SIMPLE APPLICATION");
}

void initGL()
{
    /* Create the open gl context 
     * note this uses the root window and the 
     * visual properties from earlier */
    glc = glXCreateContext(dpy, vi, NULL, GL_TRUE);

    /* Make this the current context */
    glXMakeCurrent(dpy, win, glc);

    /* depth test on */
    glEnable(GL_DEPTH_TEST); 
}

int main(int argc, char *argv[]) 
{
    makeWindow();
    
    initGL();

    /* Event loop for the window  - respond to events specified by mask */
    while(1) 
    {
        XNextEvent(dpy, &xev);
        
        if(xev.type == Expose) 
        {
                XGetWindowAttributes(dpy, win, &gwa);
                glViewport(0, 0, gwa.width, gwa.height);
                Draw(); 
                glXSwapBuffers(dpy, win);
        }        
        else if(xev.type == KeyPress) 
        {
                glXMakeCurrent(dpy, None, NULL);
                glXDestroyContext(dpy, glc);
                XDestroyWindow(dpy, win);
                XCloseDisplay(dpy);
                exit(0);
        }
    } /* this closes while(1) { */

} /* this is the } which closes int main(int argc, char *argv[]) { */
