Back to home page

EIC code displayed by LXR

 
 

    


Warning, /include/Geant4/toolx/Xt/OpenGLArea is written in an unsupported language. File is not indexed.

0001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
0002 // See the file tools.license for terms.
0003 
0004 #ifndef toolx_Xt_OpenGLArea
0005 #define toolx_Xt_OpenGLArea
0006 
0007 #include <X11/IntrinsicP.h>
0008 #include <X11/CoreP.h>
0009 #include <X11/CompositeP.h>
0010 #include <X11/StringDefs.h>
0011 
0012 #include <GL/glx.h>
0013 
0014 #include <stdio.h>
0015 #include <stdlib.h>
0016 #include <stdarg.h>
0017 
0018 namespace toolx {
0019 namespace Xt {
0020 
0021 ///////////////////////////////////////////////////////////
0022 ///////////////////////////////////////////////////////////
0023 ///////////////////////////////////////////////////////////
0024 
0025 typedef struct _OpenGLAreaClassRec* OpenGLAreaWidgetClass;
0026 typedef struct _OpenGLAreaRec* OpenGLAreaWidget;
0027 
0028 typedef struct {
0029  int reason;
0030  XEvent* event;
0031 } XoAnyCallbackStruct;
0032 
0033 #define XoCR_PAINT 1
0034 #define XoCR_EVENT 2
0035 
0036 #define XoNdoubleBufferOn toolx::Xt::OpenGLArea::XoN_doubleBufferOn()
0037 #define XoNpaintCallback  toolx::Xt::OpenGLArea::XoN_paintCallback()
0038 #define XoNeventCallback  toolx::Xt::OpenGLArea::XoN_eventCallback()
0039 
0040 ///////////////////////////////////////////////////////////
0041 ///////////////////////////////////////////////////////////
0042 ///////////////////////////////////////////////////////////
0043 
0044 typedef struct {
0045   void* extension;
0046 } OpenGLAreaClassPart;
0047 
0048 typedef struct _OpenGLAreaClassRec {
0049   CoreClassPart core_class;
0050   CompositeClassPart composite_class;
0051   OpenGLAreaClassPart openGLArea_class;
0052 } OpenGLAreaClassRec;
0053 
0054 typedef struct {
0055   Boolean doubleBufferOn;
0056   XtCallbackList paintCallback;
0057   XtCallbackList eventCallback;
0058   Visual* visual;
0059   Boolean installColormap;
0060   GLXContext glContext;
0061 } OpenGLAreaPart;
0062 
0063 typedef struct _OpenGLAreaRec {
0064   CorePart core;
0065   CompositePart composite;
0066   OpenGLAreaPart openGLArea;
0067 } OpenGLAreaRec;
0068 
0069 ///////////////////////////////////////////////////////////
0070 ///////////////////////////////////////////////////////////
0071 ///////////////////////////////////////////////////////////
0072 
0073 class OpenGLArea {
0074 protected:
0075   static const char* class_name()         {static const char* s_s = "OpenGLArea";return s_s;}
0076   static const char* XoC_DoubleBufferOn() {static const char* s_s = "DoubleBufferOn";return s_s;}
0077 public:
0078   static const char* XoN_doubleBufferOn() {static const char* s_s = "doubleBufferOn";return s_s;}
0079   static const char* XoN_paintCallback()  {static const char* s_s = "paintCallback";return s_s;}
0080   static const char* XoN_eventCallback()  {static const char* s_s = "eventCallback";return s_s;}
0081 public:
0082   static void paint(Widget a_this) {
0083     if(!XtIsRealized(a_this)) return;
0084     if(make_current(a_this)==1) {
0085       XoAnyCallbackStruct value;
0086       value.reason = XoCR_PAINT;
0087       value.event = 0;
0088       ::XtCallCallbacks(a_this,XoNpaintCallback,(XtPointer)&value);
0089       ::glXSwapBuffers(XtDisplay(a_this),XtWindow(a_this));
0090       ::glXMakeCurrent(XtDisplay(a_this),None,NULL);
0091     }
0092   }
0093 protected:
0094   static void initialize_class(void) {}
0095 
0096   static void initialize_widget(Widget a_request,Widget a_this,ArgList,Cardinal*) {
0097     if(a_request->core.width<=0)  a_this->core.width  = 100;
0098     if(a_request->core.height<=0) a_this->core.height = 100;
0099 
0100 #ifdef TOOLX_XT_OPENGLAREA_DEBUG
0101     ::printf ("debug : OpenGLArea : InitializeWidget : %s\n",::XtName(a_this));
0102 #endif
0103 
0104     OpenGLAreaPart& athis = _athis(a_this);
0105     athis.visual          = CopyFromParent;
0106     athis.installColormap = False;
0107     athis.glContext       = NULL;
0108 
0109     Display* display;
0110     Screen* screen;
0111     int iscreen;
0112     XVisualInfo* vinfo;
0113     display = XtDisplay(a_this);
0114     screen = XtScreen(a_this);
0115     iscreen = XScreenNumberOfScreen(screen);
0116   
0117    {int error,event;
0118     if(::glXQueryExtension(display,&error,&event)==0) {
0119       CWarn ("X server does not have OpenGL extensions.\n");
0120     }}
0121   
0122     if(athis.doubleBufferOn==True) {
0123       int atbs_1[] = {
0124         GLX_RGBA,
0125         GLX_RED_SIZE,   1,
0126         GLX_GREEN_SIZE, 1,
0127         GLX_BLUE_SIZE,  1,
0128         GLX_ALPHA_SIZE, 1,
0129         GLX_DEPTH_SIZE, 1,
0130         GLX_DOUBLEBUFFER,
0131         None
0132       };
0133       vinfo = ::glXChooseVisual  (display,iscreen,atbs_1);
0134       if(vinfo==NULL) { //GLX_ALPHA_SIZE : problem with Xming. Try without it.
0135         int atbs_2[] = {
0136           GLX_RGBA,
0137           GLX_RED_SIZE,   1,
0138           GLX_GREEN_SIZE, 1,
0139           GLX_BLUE_SIZE,  1,
0140           GLX_DEPTH_SIZE, 1,
0141           GLX_DOUBLEBUFFER,
0142           None
0143         };
0144         vinfo = ::glXChooseVisual  (display,iscreen,atbs_2);
0145       }
0146     } else {
0147       int atbs_1[] = {
0148         GLX_RGBA,
0149         GLX_RED_SIZE,   1,
0150         GLX_GREEN_SIZE, 1,
0151         GLX_BLUE_SIZE,  1,
0152         GLX_ALPHA_SIZE, 1,
0153         GLX_DEPTH_SIZE, 1,
0154         None
0155       };
0156       vinfo = ::glXChooseVisual  (display,iscreen,atbs_1);
0157       if(vinfo==NULL) { //GLX_ALPHA_SIZE : problem with Xming. Try without it.
0158         int atbs_2[] = {
0159           GLX_RGBA,
0160           GLX_RED_SIZE,   1,
0161           GLX_GREEN_SIZE, 1,
0162           GLX_BLUE_SIZE,  1,
0163           GLX_DEPTH_SIZE, 1,
0164           None
0165         };
0166         vinfo = ::glXChooseVisual  (display,iscreen,atbs_2);
0167       }
0168     }
0169   
0170     if(vinfo==NULL) {
0171       CWarn ("Can't choose a visual.\n");
0172     } else {
0173       a_this->core.depth = vinfo->depth;
0174       athis.visual = vinfo->visual;
0175       if( (vinfo->depth ==DefaultDepth (display,iscreen))  &&
0176           (vinfo->visual==DefaultVisual(display,iscreen)) ) {
0177         a_this->core.colormap = XDefaultColormap (display,iscreen);
0178         athis.installColormap = False;
0179       } else {
0180         a_this->core.colormap =
0181         XCreateColormap (display,XRootWindow(display,iscreen),vinfo->visual, AllocNone);
0182         athis.installColormap = True;
0183       }  
0184       if(a_this->core.colormap==0L) {
0185         CWarn ("Can't get/create a X colormap.\n");
0186       }  
0187       athis.glContext = ::glXCreateContext (display,vinfo,NULL,GL_TRUE);
0188       if(athis.glContext==NULL) {
0189         athis.glContext = ::glXCreateContext (display,vinfo,NULL,GL_FALSE);
0190         if(athis.glContext==NULL) {
0191           CWarn ("Can't create a GLX context.\n");
0192         }
0193       }
0194       ::XFree(vinfo);
0195     }
0196 
0197     ::XtAddEventHandler
0198        (a_this,ButtonPressMask|ButtonReleaseMask|ButtonMotionMask|KeyPressMask|KeyReleaseMask,0,event_handler,NULL);
0199 
0200 #ifdef TOOLX_XT_OPENGLAREA_DEBUG
0201     printf("debug : OpenGLArea : InitializeWidget : end\n");
0202 #endif
0203   }
0204 
0205   static void realize_widget(Widget a_this,XtValueMask* a_mask,XSetWindowAttributes* a_watbs) {
0206 #ifdef TOOLX_XT_OPENGLAREA_DEBUG
0207     printf("debug : OpenGLArea : realize_widget : %s\n",XtName(a_this));
0208 #endif
0209 
0210     // Have to create window ourselves due to OpenGL that compells it's visual.
0211     // In principle colormap is correctly set in a_watbsy.
0212   
0213     OpenGLAreaPart& athis = _athis(a_this);
0214     
0215     ::XtCreateWindow(a_this,(unsigned int)InputOutput,athis.visual,*a_mask,a_watbs);
0216   
0217     // Call the Realize procedure (XtInheritRealize) :
0218     if(widget_class()->core_class.superclass->core_class.realize!=NULL)
0219       (widget_class()->core_class.superclass->core_class.realize)(a_this, a_mask, a_watbs);
0220   
0221     // If window is delete, all seems ok :
0222     if(athis.installColormap==True) install_colormap(a_this);
0223   
0224     //make_current(a_this);
0225   
0226 #ifdef TOOLX_XT_OPENGLAREA_DEBUG
0227     printf("debug : OpenGLArea : realize_widget : end\n");
0228 #endif
0229   }
0230 
0231   static void destroy_widget(Widget a_this) {
0232 #ifdef TOOLX_XT_OPENGLAREA_DEBUG
0233     printf("debug : OpenGLArea : destroy_widget : begin\n");
0234 #endif
0235     OpenGLAreaPart& athis = _athis(a_this);
0236     if(athis.installColormap==True) {
0237       uninstall_colormap (a_this);
0238       athis.installColormap    = False;
0239       ::XFreeColormap(XtDisplay(a_this),a_this->core.colormap);
0240     }
0241     if(athis.glContext!=NULL) {
0242       ::glXMakeCurrent(XtDisplay(a_this),None,NULL);
0243       ::glXDestroyContext(XtDisplay(a_this),athis.glContext);
0244       athis.glContext = NULL;
0245     }
0246 #ifdef TOOLX_XT_OPENGLAREA_DEBUG
0247     printf("debug : OpenGLArea : destroy_widget : end\n");
0248 #endif
0249   }
0250 
0251   static Boolean set_values(Widget a_current,Widget,Widget a_this,ArgList,Cardinal*) {
0252     OpenGLAreaPart& athis = _athis(a_this);
0253     if(athis.doubleBufferOn != ((OpenGLAreaWidget)a_current)->openGLArea.doubleBufferOn) {
0254       // Can't change buffering here if X window is created.
0255       // With OpenGL, buffering fix parameter of the X window.
0256       // Buffering must be choosen before the execution of the
0257       // Realize method that create the window.
0258       if(XtIsRealized(a_this) && (athis.installColormap==True)) {
0259         CWarn("Can't change buffering after \"realization\" of the widget.\n");
0260         athis.doubleBufferOn = ((OpenGLAreaWidget)a_current)->openGLArea.doubleBufferOn;
0261       }
0262     }
0263     return False;
0264   }
0265   
0266   static void change_widget_size(Widget a_this) {
0267 #ifdef TOOLX_XT_OPENGLAREA_DEBUG
0268     printf("debug : OpenGLArea : change_widget_size : %s\n",XtName(a_this));
0269 #endif
0270 
0271     // Call the Resize procedure (XtInheritResize) :
0272     if(widget_class()->core_class.superclass->core_class.resize!=NULL)
0273       (widget_class()->core_class.superclass->core_class.resize)(a_this);
0274   
0275 #ifdef TOOLX_XT_OPENGLAREA_DEBUG
0276     printf("debug : OpenGLArea : change_widget_size : end\n");
0277 #endif
0278 }
0279 
0280   static void draw_widget(Widget  a_this,XEvent* a_event,Region a_region) {
0281 #ifdef TOOLX_XT_OPENGLAREA_DEBUG
0282     printf("debug : OpenGLArea : draw_widget : %s\n",XtName(a_this));
0283 #endif
0284 
0285     if(widget_class()->core_class.superclass->core_class.expose!=NULL)
0286       (widget_class()->core_class.superclass->core_class.expose)(a_this,a_event,a_region);
0287 
0288     if(make_current(a_this)==1) {
0289 #ifdef TOOLX_XT_OPENGLAREA_DEBUG
0290       printf("debug : OpenGLArea : draw_widget : %s : make_current ok : call paintCallback...\n",XtName(a_this));
0291 #endif
0292       XoAnyCallbackStruct value;
0293       value.reason = XoCR_PAINT;
0294       value.event = a_event;
0295       ::XtCallCallbacks(a_this,XoNpaintCallback,(XtPointer)&value);
0296       ::glXSwapBuffers(XtDisplay(a_this),XtWindow(a_this));
0297       ::glXMakeCurrent(XtDisplay(a_this),None,NULL);
0298     }
0299   
0300 #ifdef TOOLX_XT_OPENGLAREA_DEBUG
0301   printf("debug : OpenGLArea : draw_widget : end\n");
0302 #endif
0303   }
0304 
0305 protected:
0306   static OpenGLAreaPart& _athis(Widget a_this) {return *(&(((OpenGLAreaWidget)a_this)->openGLArea));}
0307   static void CWarn(const char* a_msg) {
0308     ::printf("%s",a_msg);
0309   }
0310   static void CWarnF(const char* a_format,...) {
0311     va_list args;
0312     va_start(args,a_format);
0313     ::vprintf(a_format,args);
0314     va_end(args);
0315   }
0316   static int make_current(Widget a_this) {
0317     if(!XtIsRealized(a_this)) return 0;
0318     OpenGLAreaPart& athis = _athis(a_this);
0319     if(athis.glContext==NULL) return 0;
0320     return (int)::glXMakeCurrent(XtDisplay(a_this),XtWindow(a_this),athis.glContext);
0321   }
0322 
0323   static void event_handler(Widget a_this,XtPointer,XEvent* a_event ,Boolean*) {
0324     XoAnyCallbackStruct value;
0325     value.reason = XoCR_EVENT;
0326     value.event = a_event;
0327     ::XtCallCallbacks(a_this,XoNeventCallback,(XtPointer)&value);
0328   }
0329 
0330   static void install_colormap(Widget a_this) {
0331     // From Mesa/widgets/GLwDrawingArea.c/post_colormap routine.
0332     // Could use also XtSetWMColormapWindows.
0333     if( !XtIsWidget(a_this) || !XtIsRealized(a_this) ) return;
0334     Widget shell = get_shell(a_this);
0335     if(shell==NULL) return;
0336     Display* display = XtDisplay (a_this);
0337     Window wthis   = XtWindow  (a_this);
0338     Window wshell  = XtWindow  (shell);
0339     Window*           ws = NULL;
0340     int               wn = 0;
0341     ::XGetWMColormapWindows (display,wshell, &ws, &wn);
0342     // Check if colormap of this is a colormap of a Window in list :
0343     XWindowAttributes watbs;
0344     XGetWindowAttributes  (display,wthis,&watbs);
0345     Colormap cmapthis = watbs.colormap;
0346     int found                 = -1;
0347     for(int count=0;count<wn;count++) {
0348       Colormap             cmap;
0349       XGetWindowAttributes (display,ws[count],&watbs);
0350       cmap                 = watbs.colormap;
0351       if(cmap==cmapthis) {
0352         ::XFree (ws);
0353         return;
0354       }
0355       if(ws[count]==wshell) {
0356         found = count;
0357       }
0358     }
0359     // Have to add window of this in list :
0360     if(wn==0) {
0361       if(ws!=NULL) ::XFree(ws);
0362       ws = (Window*)::malloc( 2 * sizeof(Window));
0363     } else {
0364       ws = (Window*)::realloc(ws,(wn + 2) * sizeof(Window));
0365     }
0366     if(ws==NULL) return;
0367     if(found==-1) {
0368       // Window of shell not in list :
0369       ws[wn] = wthis; wn++;
0370       ws[wn] = wshell;wn++;
0371     } else {
0372       ws[found] = wthis;
0373       ws[wn]    = wshell; wn++;  // Shell must be last.
0374     }
0375     if (::XSetWMColormapWindows(display,wshell, ws, wn)==0) {
0376       CWarnF ("install_colormap: can't install colormap of %s in %s.\n",XtName(a_this),XtName(shell));
0377     }
0378     ::free(ws);
0379   }
0380 
0381   static void uninstall_colormap(Widget a_this) {
0382     if( !XtIsWidget(a_this) || !XtIsRealized(a_this) ) return;
0383     Widget shell = get_shell (a_this);
0384     if(shell==NULL) return;
0385     Display* display = XtDisplay (a_this);
0386     Window wthis     = XtWindow  (a_this);
0387     Window wshell    = XtWindow  (shell);
0388     Window*           ws  = NULL;
0389     int               wn  = 0;
0390     ::XGetWMColormapWindows (display,wshell, &ws, &wn);
0391     if( (wn==0) || (ws==NULL) ) return;
0392     Window* nws = (Window*)::malloc( wn  * sizeof(Window));
0393     if(nws==NULL) {
0394       ::XFree (ws);
0395       return;
0396     }
0397     int nwn = 0;
0398     for(int count=0;count<wn;count++) {
0399       if(ws[count]!=wthis) {
0400         nws[nwn] = ws[count];
0401         nwn++;
0402       }
0403     }
0404     if(wn!=nwn) {
0405       if (::XSetWMColormapWindows(display,wshell, nws, nwn)==0) {
0406         CWarnF("uninstall_colormap: can't install colormap of %s in %s.\n",XtName(a_this),XtName(shell));
0407       }
0408     }
0409     ::XFree (ws);
0410     ::free (nws);
0411   }
0412   
0413   static Widget get_shell(Widget a_this) {
0414     Widget widget = a_this;
0415     while(1) {
0416       if(widget==NULL) return NULL;
0417       if(XtIsShell(widget)) return widget;
0418       widget = XtParent(widget);
0419     }
0420   }
0421 
0422 public:
0423   static WidgetClass widget_class() {
0424     static XtResource s_resources[] = {
0425       {(String)XoN_doubleBufferOn(),(String)XoC_DoubleBufferOn(),XtRBoolean,sizeof(Boolean),
0426        XtOffset(OpenGLAreaWidget,openGLArea.doubleBufferOn),XtRImmediate,(XtPointer)True},
0427       {(String)XoN_paintCallback(),XtCCallback,XtRCallback,sizeof(XtCallbackList),
0428        XtOffset(OpenGLAreaWidget,openGLArea.paintCallback),XtRImmediate,(XtPointer)NULL},
0429       {(String)XoN_eventCallback(),XtCCallback,XtRCallback,sizeof(XtCallbackList),
0430        XtOffset(OpenGLAreaWidget,openGLArea.eventCallback),XtRImmediate,(XtPointer)NULL}
0431     };
0432 
0433     static OpenGLAreaClassRec s_openGLAreaClassRec = {
0434       // Core Class Part :
0435       {
0436         (WidgetClass) &compositeClassRec, // pointer to superclass ClassRec   
0437         (String)class_name(),             // widget resource class name
0438         sizeof(OpenGLAreaRec),           // size in bytes of widget record   
0439         initialize_class,                // class_initialize                 
0440         NULL,                            // dynamic initialization           
0441         FALSE,                           // has class been initialized?      
0442         initialize_widget,               // initialize                       
0443         NULL,                            // notify that initialize called    
0444         realize_widget,                  // XCreateWindow for widget         
0445         NULL,                            // widget semantics name to proc mapWidget
0446         0,                               // number of entries in actions     
0447         s_resources,                     // resources for subclass fields    
0448         XtNumber(s_resources),           // number of entries in resources   
0449         NULLQUARK,                       // resource class quarkified        
0450         TRUE,                            // compress MotionNotify for widget 
0451         TRUE,                            // compress Expose events for widget
0452         TRUE,                            // compress enter and leave events  
0453         TRUE,                            // select for VisibilityNotify      
0454         destroy_widget,                  // free data for subclass pointers  
0455         change_widget_size,              // geom manager changed widget size 
0456         draw_widget,                     // rediplay window                  
0457         set_values,                      // set subclass resource values     
0458         NULL,                            // notify that SetValues called    
0459         XtInheritSetValuesAlmost,        // SetValues got "Almost" geo reply
0460         NULL,                            // notify that get_values called    
0461         XtInheritAcceptFocus,            // assign input focus to widget     
0462         XtVersion,                       // version of intrinsics used       
0463         NULL,                            // list of callback offsets         
0464         XtInheritTranslations,           // translations                     
0465         XtInheritQueryGeometry,          // return preferred geometry        
0466         XtInheritDisplayAccelerator,     // display your accelerator         
0467         NULL                             // pointer to extension record      
0468       },
0469       // Composite Class Part :
0470       {
0471         XtInheritGeometryManager,   // geometry manager for children   
0472         XtInheritChangeManaged,     // change managed state of child   
0473         XtInheritInsertChild,       // physically add child to parent  
0474         XtInheritDeleteChild,       // physically remove child             
0475         NULL                        // pointer to extension record     
0476       },
0477       // OpenGLArea :
0478       {
0479         NULL
0480       }
0481     };
0482     return (WidgetClass)&s_openGLAreaClassRec;
0483   }
0484 };
0485 
0486 }}
0487 
0488 
0489 #endif