//You can compile with GCC from terminal using:
//cc wtf2.c -o wtf2 -lX11 -lGL -lGLU
//This is written in C.
#include<stdio.h>//for UNIX terminal support
#include<stdlib.h>//some basic system functions
#include<X11/X.h>//for X window system
#include<X11/Xlib.h>//likewise
#include<GL/gl.h>//for OpenGL
#include<GL/glx.h>//likewise
#include<GL/glu.h>//likewise

int main(int argc, char** argv){//main function, argc is the number of command-line arguments (it is always 1> than the actual number of arguments because the program's name itself is considered as 0th argument, argv is the array of strings: each element is one argument: argv[0] is the program name, argv[1] is the first argument, argv[2] is the second argument..., argv[argc] is a "(null)" string
 //some excessive X11/OpenGL bloat used to initialize the window
 Display *dpy;//pointer to X display
 Window root;//this will be our root window
 GLint att[]={GLX_RGBA,GLX_DEPTH_SIZE,24,GLX_DOUBLEBUFFER,None};//these are some attributes that we need
 XVisualInfo *vi;//speaks for itself
 Colormap cmap;//description of our set of colors
 XSetWindowAttributes swa;//window attributes will be placed here
 Window win;//our window (will be placed inside the root window)
 GLXContext glc;//speaks for itself
 XWindowAttributes gwa;//speaks for itself
 XEvent xev;//X events are signals sent to a program when the user moves/clicks the mouse, presses a key on the keyboard, resized the window...

 dpy = XOpenDisplay(NULL);//lets try to open a connection to the X server (that's the part of the system that allows us to open windows)
  if(!dpy){//if we failed there's nothing we can do
   fprintf(stderr,"fatal error: cannot open X display\n");
   return 0;//end the program
  }//if we didn't fail, the program moves on
 root = DefaultRootWindow(dpy);//ask X where should we place our window (=get root window access; root window is usually the screen btw)
 vi = glXChooseVisual(dpy, 0, att);//get if necessary visual properties are available
 if(vi == NULL) {//if we can't draw proper OpenGL that's a problem
  fprintf(stderr,"fatal error: no appropriate visual found (OpenGL trouble)\n");
  XCloseDisplay(dpy);//close display access
  return 0;//end the program
 }//else, if we can draw OpenGL then lets get things started
 cmap = XCreateColormap(dpy, root, vi->visual, AllocNone);//we need some colors
 swa.colormap = cmap;
 win = XCreateWindow(dpy, root, 0, 0, 320, 240, 0, vi->depth, InputOutput, vi->visual, CWColormap | CWEventMask, &swa);//creates the window
 XMapWindow(dpy, win);//puts the window on the screen
 glc = glXCreateContext(dpy, vi, NULL, GL_TRUE);//get OpenGL started
 glXMakeCurrent(dpy, win, glc);//attach glx context to window
 glDisable(GL_DEPTH_TEST);//we'll draw 2D only so we don't need depth testing
 //end of some excessive X11/OpenGL bloat

 //window status
 typedef struct{
  unsigned int width, height;
 }Windowstatus;Windowstatus winstat;
 winstat.width=640;winstat.height=480;

 //input status (keyboard & mouse)
 typedef struct{
  unsigned char
   _esc, _f1, _f2, _f3, _f4,
   _f5, _f6, _f7, _f8,
   _f9, _f10, _f11, _f12,
   _f13, _f14, _f15, _f16,
   _printscreen, _srolllock, _pause,
   _tilde, _1, _2, _3, _4, _5, _6, _7, _8, _9, _0,
   _minus, _plus, _backspace, _tab, _enter,
   _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l,
   _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x,
   _y, _z, _lessthan, _comma, _period, _questionmark,
   _e1, _e2, _e3, _e4, _e5, _e6, _e7, _e8, _e9,//extra keys like []{}:;'"|\äëïöüšśđčćžźå... or play, pause, mail, calculator, office, web... keys
   _e10, _e11, _e12, _e13, _e14, _e15, _e16,
   _e17, _e18, _e19, _e20, _e21, _e22, _e23,
   _e24, _e25, _e26, _e27, _e28, _e29, _e30,
   _e31, _e32,//I hope that's enough
   _capslock, _lshift, _rshift, _lctrl, _rctrl,
   _lalt, _ralt, _lsuper, _rsuper, _menu,
   _int, _del, _home, _end, _pageup, _pagedown,
   _uparrow, _leftarrow, _downarrow, _rightarrow,
   _numlock, _kpslash, _kpasterisk, _kpminus,
   _kpplus, _kpenter, kpdel,
   _kp0, _kp1, _kp2, _kp3, _kp4, _kp5, _kp6, _kp7,
   _kp8, _kp9, //I hope I didn't forget anything important

   //mouse buttons, including wheel ticks
   _m1, _m2, _m3, _m4, _m5, _m6, _m7, _m8, _m9, _m10,//I hope 16 buttons is enough to cover virtually any mouse
   _m11, _m12, _m13, _m14, _m15, _m16;
  long _mx, _my;//mouse position, usually positive (between 0 and window's width/height), but a signed variable is used just in case of some buggy X implementation, to prevent needless crashing
 }Inputarray;Inputarray inarr={0};
 void Xinputevents2Inputarray(Inputarray* inarr, XEvent *xev){
  unsigned char a=0;//0 for Key/ButtonRelease, 1 for Key/ButtonPress
  if(xev->type==KeyPress || xev->type==ButtonPress){
   a=1;
  }
  if(xev->type==KeyPress || xev->type==KeyRelease){//first because a player that plays without a mouse is more likely than a player that plays without a keyboard (or, at the very least, _I_ prefer using keyboard over mouse)
   switch(xev->xkey.keycode){
    case XK_Escape:inarr->_esc=a;
    default:break;
   }
   return;
  }
  //no need for _else_ if(){} because of return;
  if(xev->type==MotionNotify){//second because if we have a mouse, it is more often moved than clicked, even if unintentionally
   inarr->_mx=xev->xmotion.x;
   inarr->_my=xev->xmotion.y;
   return;
  }
  if(xev->type==ButtonPress || xev->type==ButtonRelease){//last because see previous case
   inarr->_mx=xev->xbutton.x;//because MotionNotify events seem buggy (on my computer), i.e. they ofen do not appear
   inarr->_my=xev->xbutton.y;

   switch(xev->xbutton.button){
    case 1:inarr->_m1=a;break;
    case 2:inarr->_m2=a;break;
    case 3:inarr->_m3=a;break;
    case 4:inarr->_m4=a;break;
    case 5:inarr->_m5=a;break;
    case 6:inarr->_m6=a;break;
    case 7:inarr->_m7=a;break;
    case 8:inarr->_m8=a;break;
    case 9:inarr->_m9=a;break;
    case 10:inarr->_m10=a;break;
    case 11:inarr->_m11=a;break;
    case 12:inarr->_m12=a;break;
    case 13:inarr->_m13=a;break;
    case 14:inarr->_m14=a;break;
    case 15:inarr->_m15=a;break;
    case 16:inarr->_m16=a;break;
    default:break;
   }
   return;
  }
  //if you intent to implement joystick/whatever support, place it into another if(){} here
 }

 //set screen size
 XResizeWindow(dpy,win,winstat.width,winstat.height);
 //some OpenGL bloat
 glViewport(0, 0, winstat.width, winstat.height);
 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();
 glOrtho(0,winstat.height,winstat.width,0,0,1);
 glMatrixMode(GL_MODELVIEW);
 //end of some OpenGL bloat*/

 unsigned char running=1;
 int i,j;
 while(running){//main loop
  XFlush(dpy);
  //check X events (user input)
  while(XPending(dpy)){
   XNextEvent(dpy,&xev);
   switch (xev.type){
    case KeyPress:case KeyRelease:
    case MotionNotify:case ButtonPress:case ButtonRelease:
     Xinputevents2Inputarray(&inarr,&xev);
     break;
    case Expose:
     
     break;
    default:
     fprintf(stderr,"Unhandled X event type: %d.\n",xev.type);
   }
  }
  //draw
  glBegin(GL_POINTS);  
  for(i=1;i<1000;++i){
  
  glColor4f(0.7,0.3,0.4,0.5);//rgba
  glVertex2f(i/100,i%100);
  }
  glEnd();
  glXSwapBuffers(dpy, win);printf(".\n");system("sleep 1");

  //j=j>=200?0:j+1;
 }

  //some more X11/OpenGL bloat
  glXMakeCurrent(dpy, None, NULL);
  glXDestroyContext(dpy, glc);
  XDestroyWindow(dpy, win);
  XCloseDisplay(dpy);
  //end of some more X11/OpenGL bloat
  return 0;
}
