multi head/multi window simple program

I am trying to create a program like the example on this site under “Programming OpenGL in Linux: GLX and XLib”, but with three windows on three different monitors. For some reason the system will not compare the window variables. will work fine with one window since there is no decision to make, but when there are three windows I need to determine which window I should operate on. That’s when the if statements die and I get a segmentation fault. Help!

I have tried three times to attach the file, but the system will not upload it. I will include in the message body.


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

void DrawAQuad() {
 /*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();
}

int main (int argc, char *argv[])
{
    Display                 *display;
    XVisualInfo             *visual[3];
    GLint                   att[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None };
    Colormap                cmap;
    XSetWindowAttributes    swa_attributes[3];
    XWindowAttributes       gwa_attributes[3];
    int                     screen_num;
    int                     i;
    unsigned int            display_width[3], display_height[3];
    Window                  frame_window[3] = { 0 };
    GLXContext              glx_ctxt[3];
    XKeyEvent               event;
    display = XOpenDisplay(NULL);

  for( i = 0; i < 3; i++ )
  {
    screen_num = i+1;

    if((visual[i] = glXChooseVisual( display, screen_num, att )) == NULL )
    {
      fprintf( stdout, "No appropriate visual found.
" );
      exit( 0 );
    }
    else
    {
      fprintf( stdout, "Visual %p selected.
", (void*)visual[i]->visualid );
    }

    cmap = XCreateColormap( display,
                            XRootWindow(display, screen_num),
                            visual[i]->visual,
                            AllocNone );

    display_width[i]  = DisplayWidth(display, screen_num);
    display_height[i] = DisplayHeight(display, screen_num);

    swa_attributes[i].colormap = cmap;
    swa_attributes[i].event_mask = ExposureMask;
    swa_attributes[i].background_pixel = XBlackPixel(display, screen_num);
    swa_attributes[i].override_redirect = 1;

    /* create the application window */
    frame_window[i] = XCreateWindow( display,
                                     XRootWindow(display, screen_num),
                                     0, 0, display_width[i], display_height[i],
                                     0, visual[i]->depth, InputOutput,
                                     visual[i]->visual,
                         CWColormap|CWEventMask|CWBackPixel|CWOverrideRedirect,
                                     &swa_attributes[i]);

    XMapWindow(display, frame_window[i]);

    glx_ctxt[i] = glXCreateContext( display, visual[i], NULL, GL_TRUE );
  }

  glEnable( GL_DEPTH_TEST );

    while ( 1 ) {
        XNextEvent(display, (XEvent *)&event);

        if( event.window == frame_window[1] )
        {
          i = 0;
        }
        else if( event.window == frame_window[1] )
        {
          i = 1;
        }
        else if( event.window == frame_window[2] )
        {
          i = 2;
        }
        else
        {
          printf( "Compares failed.
" );
          i = 0;
        }

        glXMakeCurrent( display, frame_window[i], glx_ctxt[i] );

        switch ( event.type ) {
            case Expose:
            {
                XGetWindowAttributes(display, frame_window[i], &gwa_attributes[i]);
                glViewport( 0, 0, gwa_attributes[i].width, gwa_attributes[i].height );
                DrawAQuad();
                glXSwapBuffers( display, frame_window[i] );
                break;
            }
            default:
                break;
        }
    }
    return(0);
}

[QUOTE=advorak;1267509]…when there are three windows I need to determine which window I should operate on. That’s when the if statements die and I get a segmentation fault. …


if( event.window == frame_window[1] )
        {
          i = 0;
        }
        else if( event.window == frame_window[1] )
        {
          i = 1;
        }
        else if( event.window == frame_window[2] )
        {
          i = 2;
        }
        else
        {
          printf( "Compares failed.
" );
          i = 0;
        }

[/quote]

I haven’t tried your code yet (not at a Linux box now). But your first frame_window[1] should be [0] above. Not the cause of the seg fault, but nevertheless a bug.

Also, where exactly do you see a segfault?

I think you want these changes:


--- tst.old.cxx       2015-06-13 20:35:51.535304032 -0500
+++ tst.cxx     2015-06-13 20:48:59.973345849 -0500
@@ -43,8 +43,12 @@
  
   for( i = 0; i < 3; i++ )
   {
-    screen_num = i+1;
- 
+    printf( "Setting up for screen %d
", i );
+
+    //screen_num = i+1;
+    screen_num = i;                       // <----------- You're going to want this one
+    //screen_num = DefaultScreen( display );
+
     if((visual[i] = glXChooseVisual( display, screen_num, att )) == NULL )
     {
       fprintf( stdout, "No appropriate visual found.
" );
@@ -87,7 +91,8 @@
     while ( 1 ) {
         XNextEvent(display, (XEvent *)&event);
  
-        if( event.window == frame_window[1] )
+        //if( event.window == frame_window[1] )
+        if( event.window == frame_window[0] )
         {
           i = 0;
         }


First, screen numbers in the API are 0-based. So I think you’re going to want “screen = i” not “screen == i+1”. I only have one screen here, so when I tried the latter it wouldn’t even successfully query the visual for that screen (screen 1, because it doesn’t exist).

Second, you had a bug in your window matching code where it wasn’t looking at frame_window[0].

With those two changes, and forcing “screen_num = DefaultScreen( display )” here (since I only have one screen), it seems to work fine (displays image, without generating any “Compares failed.” window matching errors).

Edit: Also, follow GClements advice here:

Basically use XEvent instead of XKeyEvent.