c++linuxopenglx11slackware

X11 Window isn't updating/drawing automatically


I'm using x11(in slackware linux) as window for drawing with OpenGL.

Everything works, but somehow my x11 Window isn't updating/drawing automatically.

It only updates/draws if I resize the window.

x11 Window Code:

int main()
{

    /***************  VARIABLE DEFINITION SECTION  ***************/

    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;

    enum GAMEOBJECTS {USER, ENEMY};                     //Object Enum - to identify the objects, object must be added in same enumeration you've created the objects

    Renderer *renderer = new Renderer();                //Renderer Object


    /***************  LINUX WINDOW SETTINGS  ***************/


    dpy = XOpenDisplay(NULL);
    if(dpy == NULL)
    {
        cout << "\ncan't connect to x server\n" << endl;
        exit(0);
    }

    root = DefaultRootWindow(dpy);    
    vi = glXChooseVisual(dpy,0,att);


    if(vi == NULL)
    {
        cout << "\n no appropriate visual found \n" << endl;
        exit(0);
    }
    else
    {
        cout << "visual " << (void *)vi->visualid << "selected";
    }


    cmap = XCreateColormap(dpy, root, vi->visual, AllocNone);
    swa.colormap = cmap;
    swa.event_mask = ExposureMask | KeyPressMask;

    win = XCreateWindow(dpy,root,0,0,800,600,0,vi->depth,InputOutput,vi->visual,CWColormap | CWEventMask, &swa);


    XMapWindow(dpy,win);

    XStoreName(dpy,win,"VERY SIMPLE APP");

    glc = glXCreateContext(dpy,vi,NULL,GL_TRUE);
    glXMakeCurrent(dpy,win,glc);

    cout << "ENUM: " << USER << endl;
    cout << "ENUM: " << ENEMY << endl;

    /***************  START RENDERER AND ADD OBJECTS ***************/

    renderer->initGL();

    renderer->addObject(100,100);   // USER
    renderer->move(USER,0,-100);    //move to startposition of USER

    renderer->addObject(100,100);   // ENEMY
    renderer->move(ENEMY,0,100);    //move to startposition of ENEMY

    glEnable(GL_DEPTH_TEST);


    /***************  GAME LOOP += GAME LOOP NEEDS A OWN GAME LOOP ***************/
    int count = 0;
    while(1)
    {
        XNextEvent(dpy,&xev);
        //glViewport(0,0,gwa.width,gwa.height);
        //renderer->drawGL();

        renderer->move(ENEMY,count,100);
        if(xev.type == Expose)
        {
            XGetWindowAttributes(dpy,win,&gwa);
            glViewport(0,0,gwa.width,gwa.height);
            renderer->drawGL();     // DRAW OPENGL
            glXSwapBuffers(dpy,win);
        }

        else if(xev.type == KeyPress)
        {
            switch(XLookupKeysym(&xev.xkey,0))
            {
                case XK_Left:   cout << "LEFT KEY PRESSED" << endl;
                                renderer->move(USER,-1.0f,0.0f); //Move USER to the right
                                xev.xkey.send_event;
                                break;

                case XK_Right:  cout << "RIGHT KEY PRESSED" << endl;
                                renderer->move(USER,1.0f,0.0f); //Move USER to the right
                                break;

                case XK_Escape: glXMakeCurrent(dpy,None,NULL);
                                glXDestroyContext(dpy,glc);
                                XDestroyWindow(dpy,win);
                                XCloseDisplay(dpy);
                                exit(0);
                                break;

                case XK_P: cout << "P KEY PRESSEED" << endl;
                           break;

                case ConfigureNotify:   renderer->resizeGL(xev.xconfigure.width,xev.xconfigure.height);
                                        break;
            }

        }
        renderer->drawGL();   //DRAW OPENGL
        glXSwapBuffers(dpy,win);
        count++;
    }

    return 0;
}

Anyone can help?


Solution

  •    The XNextEvent function copies the first event from the event queue into the
       specified XEvent structure and then removes it from the queue.  If the event
       queue is empty, XNextEvent flushes the output buffer and blocks until an event
       is received.
    

    So, your call to XNextEvent waits until some event happens, and only then redraws. Worse, it redraws on every event, so if multiple events happen, you'll only know that after several frames.

    You should use XCheckWindowEvent instead, and re-organise your loop (handle all events first, then render).