Gl Graph

Gl Graph Source of glxwin.cpp


#include <glxwin.h>
 
#include <ctype.h>
#include "X11/keysymdef.h"
#include <time.h>
#include <unistd.h>
 
static void print_event(int type)
{
    switch (type)
    {
    case KeyPress:
        printf("KeyPress");
        break;
    case KeyRelease:
        printf("KeyRelease");
        break;
    case ButtonPress:
        printf("ButtonPress");
        break;
    case ButtonRelease:
        printf("ButtonRelease");
        break;
    case MotionNotify:
        printf("MotionNotify");
        break;
    case EnterNotify:
        printf("EnterNotify");
        break;
    case LeaveNotify:
        printf("LeaveNotify");
        break;
    case FocusIn:
        printf("FocusIn");
        break;
    case FocusOut:
        printf("FocusOut");
        break;
 
    case KeymapNotify:
        printf("KeymapNotify");
        break;
 
    case CreateNotify:
        printf("CreateNotify");
        break;
    case DestroyNotify:
        printf("DestroyNotify");
        break;
    case UnmapNotify:
        printf("UnmapNotify");
        break;
    case MapNotify:
        printf("MapNotify");
        break;
    case MapRequest:
        printf("MapRequest");
        break;
    }
    printf("\n");
}
 
static Bool WaitForNotify(Display *dpy, XEvent *event, XPointer arg)
{
    return (event->type == MapNotify) && (event->xmap.window == (Window) arg);
}
 
static Bool CheckEvent(Display *dpy, XEvent *event, XPointer arg)
{
    GlxWin * win = (GlxWin *) arg;
    if (win->isDebug())
        print_event(event->type);
 
    switch (event->type)
    {
    case ClientMessage:
        if ((int) event->xclient.data.l[0] == (int) win->getDeleteMsg())
        {
            win->processCloseEvent();
        }
        break;
    case ConfigureNotify:
        win->processResizeEvent(event->xconfigurerequest.width, event->xconfigurerequest.height);
        break;
    case ButtonPress:
        win->processButtonPress(event->xbutton.x, event->xbutton.y, event->xbutton.state, event->xbutton.button);
        break;
    case ButtonRelease:
        win->processButtonRelease(event->xbutton.x, event->xbutton.y, event->xbutton.state);
        break;
    case MotionNotify:
        win->processMotion(event->xmotion.x, event->xmotion.y, event->xmotion.state);
        break;
    case KeyPress:
        KeySym key;
        char buffer[20];
        int buffer_size = sizeof (buffer);
        XComposeStatus status_in_out;
        XLookupString((XKeyEvent*) event, buffer, buffer_size, &key, &status_in_out);
        if (key == XK_Escape)
            win->processButtonPressEscape();
        else if (key == XK_Left)
            win->processButtonLeft();
        else if (key == XK_Right)
            win->processButtonRight();
        else if (key == XK_Up )
            win->processButtonUp();
        else if (key == XK_Down)
            win->processButtonDown();
 
        else if (key <= XK_F12 && key >= XK_F1)
            win->processButtonPressFX(key);
        else if (isalpha(buffer[0]))
        {
            if (win->isDebug())
                printf("isalpha keycode  : %s\n", buffer);
            win->processButtonPressChar(buffer[0]);
        }
        else if (win->isDebug())
            printf("key press keycode %s\n", buffer);
        break;
    }
    return True;
}
 
 
int singleBufferAttributess[] = {
    GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
    GLX_RENDER_TYPE, GLX_RGBA_BIT,
    GLX_RED_SIZE, 1, /* Request a single buffered color buffer */
    GLX_GREEN_SIZE, 1, /* with the maximum number of color bits  */
    GLX_BLUE_SIZE, 1, /* for each component                     */
    GLX_DEPTH_SIZE, 2,
    None
};
 
int doubleBufferAttributes[] = {
    GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
    GLX_RENDER_TYPE, GLX_RGBA_BIT,
    GLX_DOUBLEBUFFER, True, /* Request a double-buffered color buffer with */
    GLX_RED_SIZE, 1, /* the maximum number of bits per component    */
    GLX_GREEN_SIZE, 1,
    GLX_BLUE_SIZE, 1,
    GLX_DEPTH_SIZE, 2,
    None
};
 
 
GlxWin::GlxWin(unsigned int width, unsigned int height)
    : GlWindow(width,height)
{
 
}
 
GlxWin::GlxWin(unsigned int width, unsigned int height, bool debug)
    : GlWindow(width,height,debug)
{
 
}
 
Atom GlxWin::getDeleteMsg()
{
    return wmDeleteMessage;
}
 
void GlxWin::processButtonPressFX(int key)
{
    switch (key)
    {
    case XK_F1:
        this->processButtonPressF1();
        break;
    case XK_F2:
        this->processButtonPressF2();
        break;
    case XK_F3:
        this->processButtonPressF3();
        break;
    case XK_F4:
        this->processButtonPressF4();
        break;
    case XK_F5:
        this->processButtonPressF5();
        break;
    case XK_F6:
        this->processButtonPressF6();
        break;
    case XK_F7:
        this->processButtonPressF7();
        break;
    case XK_F8:
        this->processButtonPressF8();
        break;
    case XK_F9:
        this->processButtonPressF9();
        break;
    case XK_F10:
        this->processButtonPressF10();
        break;
    case XK_F11:
        this->processButtonPressF11();
        break;
    case XK_F12:
        this->processButtonPressF12();
        break;
    }
}
 
 
static MouseButton convertButtonEnum(unsigned int state)
{
    MouseButton button;
 
    if (state==Button1)
    {
        button=MOUSE_BUTTON_LEFT;
    }
    else if (state==Button2)
    {
        button=MOUSE_BUTTON_MIDDLE;
    }
    else if (state==Button3)
    {
        button=MOUSE_BUTTON_RIGHT;
    }
    else if (state==Button4)
    {
        button=MOUSE_BUTTON_MIDDLE_UP;
    }
    else if (state==Button5)
    {
        button=MOUSE_BUTTON_MIDDLE_DOWN;
    }
    else
        button= MOUSE_NO_BUTTON;
 
    return button;
 
}
 
 
 
static ModifierButton convertModifierEnum(unsigned int state)
{
    ModifierButton mod;
 
    if (state & ShiftMask)
    {
        mod= SHIFT_MODIFIER;
    }
    else if (state & LockMask)
    {
        mod= LOCK_MODIFIER;
    }
    else if (state & ControlMask)
    {
        mod= CTRL_MODIFIER ;
    }
    else if (state & Mod1Mask)
    {
        mod= ALT_MODIFIER;
    }
    else
        mod= NO_MODIFIER;
 
    return mod;
 
}
 
 
void GlxWin::processButtonPress(int x, int y, unsigned int state, unsigned int button)
{
    currentButton =convertButtonEnum(button);
    ModifierButton mod = convertModifierEnum(state);
    onMouseButtonPress(x,y,currentButton,mod);
}
 
void GlxWin::processButtonRelease(int x, int y, unsigned int state)
{
    ModifierButton mod = convertModifierEnum(state);
    onMouseButtonRelease(x,y,currentButton,mod);
    currentButton=MOUSE_NO_BUTTON;
}
 
void GlxWin::processMotion(int x, int y, unsigned int state)
{
    ModifierButton mod = convertModifierEnum(state);
    onMouseMotion(x,y,currentButton,mod);
}
 
void GlxWin::initGl()
{
 
    /* Open a connection to the X server */
    dpy = XOpenDisplay(NULL);
    if (dpy == NULL)
    {
        printf("Unable to open a connection to the X server\n");
        exit(EXIT_FAILURE);
    }
 
    char * ServerVendor = XServerVendor(dpy);
    if (ServerVendor != NULL)
    {
        printf("ServerVendor %s \n", ServerVendor);
    }
    else
    {
        printf("Unable get ServerVendor\n");
    }
 
 
    char * DisplayString = XDisplayString(dpy);
    if (DisplayString != NULL)
    {
        printf("DisplayString %s \n", DisplayString);
    }
    else
    {
        printf("Unable get DisplayString\n");
    }
 
 
    printf("X %i Y %i\n", XDisplayWidth(dpy, 0), XDisplayHeight(dpy, 0));
    printf("width %i height %i\n", width, height);
 
 
 
    int numReturned;
    /* Request a suitable framebuffer configuration - try for a double
     ** buffered configuration first */
    fbConfigs = glXChooseFBConfig(dpy, DefaultScreen(dpy), doubleBufferAttributes, &numReturned);
 
    if (fbConfigs == NULL)
    {   /* no double buffered configs available */
        fbConfigs = glXChooseFBConfig(dpy, DefaultScreen(dpy), singleBufferAttributess, &numReturned);
        swapFlag = False;
    }
    else
    {
        swapFlag = True;
    }
 
    /* Create an X colormap and window with a visual matching the first
     ** returned framebuffer config */
    vInfo = glXGetVisualFromFBConfig(dpy, fbConfigs[0]);
 
    swa.border_pixel = 0;
 
    int key_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask;
    swa.event_mask = StructureNotifyMask | key_mask;
    swa.colormap = XCreateColormap(dpy, RootWindow(dpy, vInfo->screen), vInfo->visual, AllocNone);
 
    swaMask = CWBorderPixel | CWColormap | CWEventMask;
 
 
    xWin = XCreateWindow(dpy, RootWindow(dpy, vInfo->screen), 0, 0, width, height,
                         0, vInfo->depth, InputOutput, vInfo->visual,
                         swaMask, &swa);
 
    /* Create a GLX context for OpenGL rendering */
    context = glXCreateNewContext(dpy, fbConfigs[0], GLX_RGBA_TYPE, NULL, True);
 
    /* Create a GLX window to associate the frame buffer configuration
     ** with the created X window */
    win = glXCreateWindow(dpy, fbConfigs[0], xWin, NULL);
 
    /* Map the window to the screen, and wait for it to appear */
    XMapWindow(dpy, xWin);
    XIfEvent(dpy, &event, WaitForNotify, (XPointer) xWin);
    wmDeleteMessage = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
    XSetWMProtocols(dpy, xWin, &wmDeleteMessage, 1);
 
    /* Bind the GLX context to the Window */
    glXMakeContextCurrent(dpy, win, win, context);
 
 
 
}
 
void GlxWin::initAfterGl(DrawableSet * set)
{
    GlWindow::initAfterGl(set);
 
    if (scene->getVersion()->hasGlEXTENSION("GLX_EXT_swap_control") )
    {
        typedef void (*glXSwapIntervalEXTPtr)(int);
        glXSwapIntervalEXTPtr glXSwapInterval = (glXSwapIntervalEXTPtr) glXGetProcAddress((const GLubyte*)"glXSwapIntervalEXT");
        glXSwapInterval(-1);
    }
}
 
 
void GlxWin::setTitle(const char* title)
{
    name.value = (unsigned char*) title;
    name.encoding = XA_STRING;
    name.format = 8;
    name.nitems = strlen(title);
    XSetWMName(dpy, xWin, &name);
}
 
 
void GlxWin::swapBuffers()
{
    if (swapFlag)
        glXSwapBuffers(dpy, win);
}
void GlxWin::checkEvent()
{
    while (XCheckIfEvent(dpy, &event, CheckEvent, (XPointer) this));
}
void GlxWin::destroyWindow()
{
    XDestroyWindow(dpy, xWin);
}
 
void GlxWin::run()
{
 
    const int delay = lrint(1000000.0 / 60.0);
    unsigned int t = 0;
 
 
    while (!stopped)
    {
 
        if (this->helpTextMode)
            drawHelpText();
        else
            drawAll();
 
 
        usleep(delay);
        swapBuffers();
        checkEvent();
        t = t + 1;
    }
 
    destroyWindow();
 
}