rem: drawThread[i]->runFunction( drawThreadProc, 0, (void *)i );
add: drawThread[i]->runFunction( drawThreadProc, 0, (void *)&ids[i] );
context: int main (int argc, char **argv){    int i,        eventThread,        dummy;    // OSG init    osgInit(argc, argv);    basetime = getSystemTime();    gThreadManager = ThreadManager::the();      // create the graph    // beacon for camera and light      NodePtr b1n = Node::create();    GroupPtr b1 = Group::create();    beginEditCP(b1n);    b1n->setCore( b1 );    endEditCP(b1n);        // light        NodePtr dlight = Node::create();    DirectionalLightPtr dl = DirectionalLight::create();    beginEditCP(dlight);    dlight->setCore( dl );    endEditCP(dlight);        beginEditCP(dl);    dl->setAmbient( .3, .3, .3, 1 );    dl->setDiffuse( 1, 1, 1, 1 );    dl->setDirection(0,0,1);    dl->setBeacon( b1n);    endEditCP(dl);    // root    root = Node::create();    GroupPtr gr1 = Group::create();    beginEditCP(root);    root->setCore( gr1 );    // transformation            NodePtr t1n = Node::create();    TransformPtr t1 = Transform::create();    beginEditCP(t1n);    t1n->setCore( t1 );    t1n->addChild( b1n );    endEditCP(t1n);    cam_trans = t1;    root->addChild( t1n );    root->addChild( dlight );    endEditCP(root);    // Load the file    NodePtr file = NullFC;        if ( argc > 1 )    {        file = SceneFileHandler::the().read(argv[1]);        argc--, argv++;    }        if ( file == NullFC )    {        std::cerr << "Couldn't load file, ignoring" << std::endl;        file = makeTorus( .5, 2, 16, 16 );    }        file->updateVolume();    Vec3f min,max;    file->getVolume().getBounds( min, max );        std::cout << "Volume: from " << min << " to " << max << std::endl;    beginEditCP(dlight);    dlight->addChild( file );    endEditCP(dlight);    // Background    SolidBackgroundPtr bkgnd = SolidBackground::create();    // set up some default windows, if none given        if(argc < 2)    {        static char *defarg[] = { "testWindowMTX", NULL, NULL };        argc = 3;        argv = defarg;           }        // tball    Vec3f pos( 0, 0, max[2] + ( max[2] - min[2] ) * 1.5 );        tball.setMode( Trackball::OSGObject );    tball.setStartPosition( pos, true );    tball.setSum( true );    tball.setTranslationMode( Trackball::OSGFree );    // Camera    cam = PerspectiveCamera::create();    cam->setBeacon( (*(cam_trans->getMFParents()))[0] );    cam->setFov( deg2rad( 60 ) );    cam->setNear( 0.1 );    cam->setFar( 10000 );    // X init    // Create Windows        usedThreads = argc - 1;        for ( i = 0; i < usedThreads; i++ )    {           // Create a Window and connect it to the main display dpy        dpy[i] = XOpenDisplay(argv[i+1]);        if (dpy[i] == NULL)         {            std::cerr << "Error: Could not open display!" << std::endl;        }        if(!glXQueryExtension(dpy[i], &dummy, &dummy))        {            std::cerr << "Error: X server has no OpenGL GLX extension" << std::endl;        }        vi = glXChooseVisual(dpy[i], DefaultScreen(dpy[i]), dblBuf);        if ( vi == NULL )         {           vi = glXChooseVisual(dpy[i], DefaultScreen(dpy[i]), snglBuf);           if (vi == NULL)           {               std::cerr << "no RGB visual with depth buffer" << std::endl;           }           doubleBuffer = GL_FALSE;        }        if (vi->c_class != TrueColor)        {            std::cerr << "TrueColor visual required for this program" << std::endl;        }        cmap = XCreateColormap(dpy[i], RootWindow(dpy[i], vi->screen), vi->visual, AllocNone);        swa.colormap = cmap;        swa.border_pixel = 0;        swa.event_mask = ExposureMask |                          ButtonPressMask |                          ButtonReleaseMask |                         KeyPressMask |                         Button1MotionMask |                         Button2MotionMask |                         Button3MotionMask |                          StructureNotifyMask;                    hwin[i] = XCreateWindow(dpy[i], RootWindow(dpy[i], vi->screen), 0, 0, 300, 300, 0, vi->depth,                                InputOutput, vi->visual, CWBorderPixel | CWColormap | CWEventMask, &swa);        XSetStandardProperties(dpy[i], hwin[i], "testWindowX", "testWindowX", None, argv, argc, NULL);                XMapWindow(dpy[i], hwin[i]);        XIfEvent(dpy[i], &event, wait_for_map_notify, (char *)hwin[i]);        win[i] = XWindow::create();        win[i]->setDisplay ( dpy[i] );        win[i]->setWindow ( hwin[i] );        win[i]->init();        win[i]->deactivate();              // Viewport            ViewportPtr vp = Viewport::create();        vp->setCamera( cam );        vp->setBackground( bkgnd );        vp->setRoot( root );        vp->setSize( 0,0, 1,1 );        win[i]->addPort( vp );                  lastx[i] = 0;        lasty[i] = 0;            // Action            ract[i] = RenderAction::create();    }        for (i = 0; i < usedThreads; i++)    {                       // reset thread stop/resize notify variables        drawThreadStop[i] = false;        // get new thread        drawThread[i] =             dynamic_cast<Thread *>(gThreadManager->getThread(NULL));        if ( drawThread[i] != NULL )   // and spin it ...        {                  drawThread[i]->runFunction( drawThreadProc, 0, (void *)i );        }    }    // main loop ( event dispatching )    Real32 w,h,a,b,c,d;        while ( !stopIt )     {        for (int i=0;i<usedThreads;i++)        {            while ( XPending(dpy[i]) )            {                XNextEvent(dpy[i], &event);                eventThread = i;                dpr << "for thread " << eventThread << " ... ";                switch (event.type)                 {                    case KeyPress:                                   std::cout << "Key pressed: " << event.xkey.keycode << std::endl;                        switch ( event.xkey.keycode )                         {                            case 16:                                 stopIt = true;                                break;                        }                        break;                    case ButtonPress:                        std::cout << "Button pressed: " << event.xbutton.button << std::endl;                                         switch ( event.xbutton.button )                         {                                                   case 2:                                tball.setAutoPosition(true);                                break;                            case 3:                                tball.setAutoPositionNeg(true);                        }                        lastx[eventThread] = event.xbutton.x;                        lasty[eventThread] = event.xbutton.y;                        break;                    case ButtonRelease:                        std::cout << "Button released: " << event.xbutton.button << std::endl;                                            switch ( event.xbutton.button )                         {                                                   case 2:                                tball.setAutoPosition(false);                                 break;                            case 3:                                tball.setAutoPositionNeg(false);                        }                        lastx[eventThread] = event.xbutton.x;                        lasty[eventThread] = event.xbutton.y;                        break;                    case MotionNotify:                        std::cout << "MotionNotify" << std::endl;                        w = win[eventThread]->getWidth();                        h = win[eventThread]->getHeight();                        a = -2. * ( lastx[eventThread] / w - .5 );                        b = -2. * ( .5 - lasty[eventThread] / h );                        c = -2. * ( event.xmotion.x / w - .5 );                        d = -2. * ( .5 - event.xmotion.y / h );                        if ( event.xmotion.state & Button1MotionMask )                        {                            tball.updateRotation( a, b, c, d );                        }                        if ( event.xmotion.state & Button2MotionMask )                        {                            tball.updatePosition( a, b, c, d );                        }                        if ( event.xmotion.state & Button3MotionMask )                        {                            tball.updatePositionNeg( a, b, c, d );                        }                        lastx[eventThread] = event.xmotion.x;                        lasty[eventThread] = event.xmotion.y;                        break;                    case ConfigureNotify:                        std::cout << "ConfigureNotify" << std::endl;                        if ( ! win[eventThread]->isResizePending() )                        {                            win[eventThread]->resize( event.xconfigure.width,                                                      event.xconfigure.height );                        }                                    default: std::cout << "unhandled" << std::endl;                  }            }         }    }         for ( i=0; i<usedThreads; i++ )    {        drawThreadStop[i] = 1;        Thread::join( drawThread[i] );    }    return (0);}