Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/externals/g4tools/include/toolx/Xt/OpenGLArea

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  1 // Copyright (C) 2010, Guy Barrand. All rights reserved.
  2 // See the file tools.license for terms.
  3 
  4 #ifndef toolx_Xt_OpenGLArea
  5 #define toolx_Xt_OpenGLArea
  6 
  7 #include <X11/IntrinsicP.h>
  8 #include <X11/CoreP.h>
  9 #include <X11/CompositeP.h>
 10 #include <X11/StringDefs.h>
 11 
 12 #include <GL/glx.h>
 13 
 14 #include <stdio.h>
 15 #include <stdlib.h>
 16 #include <stdarg.h>
 17 
 18 namespace toolx {
 19 namespace Xt {
 20 
 21 ///////////////////////////////////////////////////////////
 22 ///////////////////////////////////////////////////////////
 23 ///////////////////////////////////////////////////////////
 24 
 25 typedef struct _OpenGLAreaClassRec* OpenGLAreaWidgetClass;
 26 typedef struct _OpenGLAreaRec* OpenGLAreaWidget;
 27 
 28 typedef struct {
 29  int reason;
 30  XEvent* event;
 31 } XoAnyCallbackStruct;
 32 
 33 #define XoCR_PAINT 1
 34 #define XoCR_EVENT 2
 35 
 36 #define XoNdoubleBufferOn toolx::Xt::OpenGLArea::XoN_doubleBufferOn()
 37 #define XoNpaintCallback  toolx::Xt::OpenGLArea::XoN_paintCallback()
 38 #define XoNeventCallback  toolx::Xt::OpenGLArea::XoN_eventCallback()
 39 
 40 ///////////////////////////////////////////////////////////
 41 ///////////////////////////////////////////////////////////
 42 ///////////////////////////////////////////////////////////
 43 
 44 typedef struct {
 45   void* extension;
 46 } OpenGLAreaClassPart;
 47 
 48 typedef struct _OpenGLAreaClassRec {
 49   CoreClassPart core_class;
 50   CompositeClassPart composite_class;
 51   OpenGLAreaClassPart openGLArea_class;
 52 } OpenGLAreaClassRec;
 53 
 54 typedef struct {
 55   Boolean doubleBufferOn;
 56   XtCallbackList paintCallback;
 57   XtCallbackList eventCallback;
 58   Visual* visual;
 59   Boolean installColormap;
 60   GLXContext glContext;
 61 } OpenGLAreaPart;
 62 
 63 typedef struct _OpenGLAreaRec {
 64   CorePart core;
 65   CompositePart composite;
 66   OpenGLAreaPart openGLArea;
 67 } OpenGLAreaRec;
 68 
 69 ///////////////////////////////////////////////////////////
 70 ///////////////////////////////////////////////////////////
 71 ///////////////////////////////////////////////////////////
 72 
 73 class OpenGLArea {
 74 protected:
 75   static const char* class_name()         {static const char* s_s = "OpenGLArea";return s_s;}
 76   static const char* XoC_DoubleBufferOn() {static const char* s_s = "DoubleBufferOn";return s_s;}
 77 public:
 78   static const char* XoN_doubleBufferOn() {static const char* s_s = "doubleBufferOn";return s_s;}
 79   static const char* XoN_paintCallback()  {static const char* s_s = "paintCallback";return s_s;}
 80   static const char* XoN_eventCallback()  {static const char* s_s = "eventCallback";return s_s;}
 81 public:
 82   static void paint(Widget a_this) {
 83     if(!XtIsRealized(a_this)) return;
 84     if(make_current(a_this)==1) {
 85       XoAnyCallbackStruct value;
 86       value.reason = XoCR_PAINT;
 87       value.event = 0;
 88       ::XtCallCallbacks(a_this,XoNpaintCallback,(XtPointer)&value);
 89       ::glXSwapBuffers(XtDisplay(a_this),XtWindow(a_this));
 90       ::glXMakeCurrent(XtDisplay(a_this),None,NULL);
 91     }
 92   }
 93 protected:
 94   static void initialize_class(void) {}
 95 
 96   static void initialize_widget(Widget a_request,Widget a_this,ArgList,Cardinal*) {
 97     if(a_request->core.width<=0)  a_this->core.width  = 100;
 98     if(a_request->core.height<=0) a_this->core.height = 100;
 99 
100 #ifdef TOOLX_XT_OPENGLAREA_DEBUG
101     ::printf ("debug : OpenGLArea : InitializeWidget : %s\n",::XtName(a_this));
102 #endif
103 
104     OpenGLAreaPart& athis = _athis(a_this);
105     athis.visual          = CopyFromParent;
106     athis.installColormap = False;
107     athis.glContext       = NULL;
108 
109     Display* display;
110     Screen* screen;
111     int iscreen;
112     XVisualInfo* vinfo;
113     display = XtDisplay(a_this);
114     screen = XtScreen(a_this);
115     iscreen = XScreenNumberOfScreen(screen);
116   
117    {int error,event;
118     if(::glXQueryExtension(display,&error,&event)==0) {
119       CWarn ("X server does not have OpenGL extensions.\n");
120     }}
121   
122     if(athis.doubleBufferOn==True) {
123       int atbs_1[] = {
124         GLX_RGBA,
125         GLX_RED_SIZE,   1,
126         GLX_GREEN_SIZE, 1,
127         GLX_BLUE_SIZE,  1,
128         GLX_ALPHA_SIZE, 1,
129         GLX_DEPTH_SIZE, 1,
130         GLX_DOUBLEBUFFER,
131         None
132       };
133       vinfo = ::glXChooseVisual  (display,iscreen,atbs_1);
134       if(vinfo==NULL) { //GLX_ALPHA_SIZE : problem with Xming. Try without it.
135         int atbs_2[] = {
136           GLX_RGBA,
137           GLX_RED_SIZE,   1,
138           GLX_GREEN_SIZE, 1,
139           GLX_BLUE_SIZE,  1,
140           GLX_DEPTH_SIZE, 1,
141           GLX_DOUBLEBUFFER,
142           None
143         };
144         vinfo = ::glXChooseVisual  (display,iscreen,atbs_2);
145       }
146     } else {
147       int atbs_1[] = {
148         GLX_RGBA,
149         GLX_RED_SIZE,   1,
150         GLX_GREEN_SIZE, 1,
151         GLX_BLUE_SIZE,  1,
152         GLX_ALPHA_SIZE, 1,
153         GLX_DEPTH_SIZE, 1,
154         None
155       };
156       vinfo = ::glXChooseVisual  (display,iscreen,atbs_1);
157       if(vinfo==NULL) { //GLX_ALPHA_SIZE : problem with Xming. Try without it.
158         int atbs_2[] = {
159           GLX_RGBA,
160           GLX_RED_SIZE,   1,
161           GLX_GREEN_SIZE, 1,
162           GLX_BLUE_SIZE,  1,
163           GLX_DEPTH_SIZE, 1,
164           None
165         };
166         vinfo = ::glXChooseVisual  (display,iscreen,atbs_2);
167       }
168     }
169   
170     if(vinfo==NULL) {
171       CWarn ("Can't choose a visual.\n");
172     } else {
173       a_this->core.depth = vinfo->depth;
174       athis.visual = vinfo->visual;
175       if( (vinfo->depth ==DefaultDepth (display,iscreen))  &&
176           (vinfo->visual==DefaultVisual(display,iscreen)) ) {
177         a_this->core.colormap = XDefaultColormap (display,iscreen);
178         athis.installColormap = False;
179       } else {
180         a_this->core.colormap =
181     XCreateColormap (display,XRootWindow(display,iscreen),vinfo->visual, AllocNone);
182         athis.installColormap = True;
183       }  
184       if(a_this->core.colormap==0L) {
185         CWarn ("Can't get/create a X colormap.\n");
186       }  
187       athis.glContext = ::glXCreateContext (display,vinfo,NULL,GL_TRUE);
188       if(athis.glContext==NULL) {
189         athis.glContext = ::glXCreateContext (display,vinfo,NULL,GL_FALSE);
190         if(athis.glContext==NULL) {
191           CWarn ("Can't create a GLX context.\n");
192         }
193       }
194       ::XFree(vinfo);
195     }
196 
197     ::XtAddEventHandler
198        (a_this,ButtonPressMask|ButtonReleaseMask|ButtonMotionMask|KeyPressMask|KeyReleaseMask,0,event_handler,NULL);
199 
200 #ifdef TOOLX_XT_OPENGLAREA_DEBUG
201     printf("debug : OpenGLArea : InitializeWidget : end\n");
202 #endif
203   }
204 
205   static void realize_widget(Widget a_this,XtValueMask* a_mask,XSetWindowAttributes* a_watbs) {
206 #ifdef TOOLX_XT_OPENGLAREA_DEBUG
207     printf("debug : OpenGLArea : realize_widget : %s\n",XtName(a_this));
208 #endif
209 
210     // Have to create window ourselves due to OpenGL that compells it's visual.
211     // In principle colormap is correctly set in a_watbsy.
212   
213     OpenGLAreaPart& athis = _athis(a_this);
214     
215     ::XtCreateWindow(a_this,(unsigned int)InputOutput,athis.visual,*a_mask,a_watbs);
216   
217     // Call the Realize procedure (XtInheritRealize) :
218     if(widget_class()->core_class.superclass->core_class.realize!=NULL)
219       (widget_class()->core_class.superclass->core_class.realize)(a_this, a_mask, a_watbs);
220   
221     // If window is delete, all seems ok :
222     if(athis.installColormap==True) install_colormap(a_this);
223   
224     //make_current(a_this);
225   
226 #ifdef TOOLX_XT_OPENGLAREA_DEBUG
227     printf("debug : OpenGLArea : realize_widget : end\n");
228 #endif
229   }
230 
231   static void destroy_widget(Widget a_this) {
232 #ifdef TOOLX_XT_OPENGLAREA_DEBUG
233     printf("debug : OpenGLArea : destroy_widget : begin\n");
234 #endif
235     OpenGLAreaPart& athis = _athis(a_this);
236     if(athis.installColormap==True) {
237       uninstall_colormap (a_this);
238       athis.installColormap    = False;
239       ::XFreeColormap(XtDisplay(a_this),a_this->core.colormap);
240     }
241     if(athis.glContext!=NULL) {
242       ::glXMakeCurrent(XtDisplay(a_this),None,NULL);
243       ::glXDestroyContext(XtDisplay(a_this),athis.glContext);
244       athis.glContext = NULL;
245     }
246 #ifdef TOOLX_XT_OPENGLAREA_DEBUG
247     printf("debug : OpenGLArea : destroy_widget : end\n");
248 #endif
249   }
250 
251   static Boolean set_values(Widget a_current,Widget,Widget a_this,ArgList,Cardinal*) {
252     OpenGLAreaPart& athis = _athis(a_this);
253     if(athis.doubleBufferOn != ((OpenGLAreaWidget)a_current)->openGLArea.doubleBufferOn) {
254       // Can't change buffering here if X window is created.
255       // With OpenGL, buffering fix parameter of the X window.
256       // Buffering must be choosen before the execution of the
257       // Realize method that create the window.
258       if(XtIsRealized(a_this) && (athis.installColormap==True)) {
259         CWarn("Can't change buffering after \"realization\" of the widget.\n");
260         athis.doubleBufferOn = ((OpenGLAreaWidget)a_current)->openGLArea.doubleBufferOn;
261       }
262     }
263     return False;
264   }
265   
266   static void change_widget_size(Widget a_this) {
267 #ifdef TOOLX_XT_OPENGLAREA_DEBUG
268     printf("debug : OpenGLArea : change_widget_size : %s\n",XtName(a_this));
269 #endif
270 
271     // Call the Resize procedure (XtInheritResize) :
272     if(widget_class()->core_class.superclass->core_class.resize!=NULL)
273       (widget_class()->core_class.superclass->core_class.resize)(a_this);
274   
275 #ifdef TOOLX_XT_OPENGLAREA_DEBUG
276     printf("debug : OpenGLArea : change_widget_size : end\n");
277 #endif
278 }
279 
280   static void draw_widget(Widget  a_this,XEvent* a_event,Region a_region) {
281 #ifdef TOOLX_XT_OPENGLAREA_DEBUG
282     printf("debug : OpenGLArea : draw_widget : %s\n",XtName(a_this));
283 #endif
284 
285     if(widget_class()->core_class.superclass->core_class.expose!=NULL)
286       (widget_class()->core_class.superclass->core_class.expose)(a_this,a_event,a_region);
287 
288     if(make_current(a_this)==1) {
289 #ifdef TOOLX_XT_OPENGLAREA_DEBUG
290       printf("debug : OpenGLArea : draw_widget : %s : make_current ok : call paintCallback...\n",XtName(a_this));
291 #endif
292       XoAnyCallbackStruct value;
293       value.reason = XoCR_PAINT;
294       value.event = a_event;
295       ::XtCallCallbacks(a_this,XoNpaintCallback,(XtPointer)&value);
296       ::glXSwapBuffers(XtDisplay(a_this),XtWindow(a_this));
297       ::glXMakeCurrent(XtDisplay(a_this),None,NULL);
298     }
299   
300 #ifdef TOOLX_XT_OPENGLAREA_DEBUG
301   printf("debug : OpenGLArea : draw_widget : end\n");
302 #endif
303   }
304 
305 protected:
306   static OpenGLAreaPart& _athis(Widget a_this) {return *(&(((OpenGLAreaWidget)a_this)->openGLArea));}
307   static void CWarn(const char* a_msg) {
308     ::printf("%s",a_msg);
309   }
310   static void CWarnF(const char* a_format,...) {
311     va_list args;
312     va_start(args,a_format);
313     ::vprintf(a_format,args);
314     va_end(args);
315   }
316   static int make_current(Widget a_this) {
317     if(!XtIsRealized(a_this)) return 0;
318     OpenGLAreaPart& athis = _athis(a_this);
319     if(athis.glContext==NULL) return 0;
320     return (int)::glXMakeCurrent(XtDisplay(a_this),XtWindow(a_this),athis.glContext);
321   }
322 
323   static void event_handler(Widget a_this,XtPointer,XEvent* a_event ,Boolean*) {
324     XoAnyCallbackStruct value;
325     value.reason = XoCR_EVENT;
326     value.event = a_event;
327     ::XtCallCallbacks(a_this,XoNeventCallback,(XtPointer)&value);
328   }
329 
330   static void install_colormap(Widget a_this) {
331     // From Mesa/widgets/GLwDrawingArea.c/post_colormap routine.
332     // Could use also XtSetWMColormapWindows.
333     if( !XtIsWidget(a_this) || !XtIsRealized(a_this) ) return;
334     Widget shell = get_shell(a_this);
335     if(shell==NULL) return;
336     Display* display = XtDisplay (a_this);
337     Window wthis   = XtWindow  (a_this);
338     Window wshell  = XtWindow  (shell);
339     Window*           ws = NULL;
340     int               wn = 0;
341     ::XGetWMColormapWindows (display,wshell, &ws, &wn);
342     // Check if colormap of this is a colormap of a Window in list :
343     XWindowAttributes watbs;
344     XGetWindowAttributes  (display,wthis,&watbs);
345     Colormap cmapthis = watbs.colormap;
346     int found                 = -1;
347     for(int count=0;count<wn;count++) {
348       Colormap             cmap;
349       XGetWindowAttributes (display,ws[count],&watbs);
350       cmap                 = watbs.colormap;
351       if(cmap==cmapthis) {
352         ::XFree (ws);
353         return;
354       }
355       if(ws[count]==wshell) {
356         found = count;
357       }
358     }
359     // Have to add window of this in list :
360     if(wn==0) {
361       if(ws!=NULL) ::XFree(ws);
362       ws = (Window*)::malloc( 2 * sizeof(Window));
363     } else {
364       ws = (Window*)::realloc(ws,(wn + 2) * sizeof(Window));
365     }
366     if(ws==NULL) return;
367     if(found==-1) {
368       // Window of shell not in list :
369       ws[wn] = wthis; wn++;
370       ws[wn] = wshell;wn++;
371     } else {
372       ws[found] = wthis;
373       ws[wn]    = wshell; wn++;  // Shell must be last.
374     }
375     if (::XSetWMColormapWindows(display,wshell, ws, wn)==0) {
376       CWarnF ("install_colormap: can't install colormap of %s in %s.\n",XtName(a_this),XtName(shell));
377     }
378     ::free(ws);
379   }
380 
381   static void uninstall_colormap(Widget a_this) {
382     if( !XtIsWidget(a_this) || !XtIsRealized(a_this) ) return;
383     Widget shell = get_shell (a_this);
384     if(shell==NULL) return;
385     Display* display = XtDisplay (a_this);
386     Window wthis     = XtWindow  (a_this);
387     Window wshell    = XtWindow  (shell);
388     Window*           ws  = NULL;
389     int               wn  = 0;
390     ::XGetWMColormapWindows (display,wshell, &ws, &wn);
391     if( (wn==0) || (ws==NULL) ) return;
392     Window* nws = (Window*)::malloc( wn  * sizeof(Window));
393     if(nws==NULL) {
394       ::XFree (ws);
395       return;
396     }
397     int nwn = 0;
398     for(int count=0;count<wn;count++) {
399       if(ws[count]!=wthis) {
400         nws[nwn] = ws[count];
401         nwn++;
402       }
403     }
404     if(wn!=nwn) {
405       if (::XSetWMColormapWindows(display,wshell, nws, nwn)==0) {
406         CWarnF("uninstall_colormap: can't install colormap of %s in %s.\n",XtName(a_this),XtName(shell));
407       }
408     }
409     ::XFree (ws);
410     ::free (nws);
411   }
412   
413   static Widget get_shell(Widget a_this) {
414     Widget widget = a_this;
415     while(1) {
416       if(widget==NULL) return NULL;
417       if(XtIsShell(widget)) return widget;
418       widget = XtParent(widget);
419     }
420   }
421 
422 public:
423   static WidgetClass widget_class() {
424     static XtResource s_resources[] = {
425       {(String)XoN_doubleBufferOn(),(String)XoC_DoubleBufferOn(),XtRBoolean,sizeof(Boolean),
426        XtOffset(OpenGLAreaWidget,openGLArea.doubleBufferOn),XtRImmediate,(XtPointer)True},
427       {(String)XoN_paintCallback(),XtCCallback,XtRCallback,sizeof(XtCallbackList),
428        XtOffset(OpenGLAreaWidget,openGLArea.paintCallback),XtRImmediate,(XtPointer)NULL},
429       {(String)XoN_eventCallback(),XtCCallback,XtRCallback,sizeof(XtCallbackList),
430        XtOffset(OpenGLAreaWidget,openGLArea.eventCallback),XtRImmediate,(XtPointer)NULL}
431     };
432 
433     static OpenGLAreaClassRec s_openGLAreaClassRec = {
434       // Core Class Part :
435       {
436         (WidgetClass) &compositeClassRec, // pointer to superclass ClassRec   
437         (String)class_name(),             // widget resource class name
438         sizeof(OpenGLAreaRec),           // size in bytes of widget record   
439         initialize_class,                // class_initialize                 
440         NULL,                            // dynamic initialization           
441         FALSE,                           // has class been initialized?      
442         initialize_widget,               // initialize                       
443         NULL,                            // notify that initialize called    
444         realize_widget,                  // XCreateWindow for widget         
445         NULL,                            // widget semantics name to proc mapWidget
446         0,                               // number of entries in actions     
447         s_resources,                     // resources for subclass fields    
448         XtNumber(s_resources),           // number of entries in resources   
449         NULLQUARK,                       // resource class quarkified        
450         TRUE,                            // compress MotionNotify for widget 
451         TRUE,                            // compress Expose events for widget
452         TRUE,                            // compress enter and leave events  
453         TRUE,                            // select for VisibilityNotify      
454         destroy_widget,                  // free data for subclass pointers  
455         change_widget_size,              // geom manager changed widget size 
456         draw_widget,                     // rediplay window                  
457         set_values,                      // set subclass resource values     
458         NULL,                            // notify that SetValues called    
459         XtInheritSetValuesAlmost,        // SetValues got "Almost" geo reply
460         NULL,                            // notify that get_values called    
461         XtInheritAcceptFocus,            // assign input focus to widget     
462         XtVersion,                       // version of intrinsics used       
463         NULL,                            // list of callback offsets         
464         XtInheritTranslations,           // translations                     
465         XtInheritQueryGeometry,          // return preferred geometry        
466         XtInheritDisplayAccelerator,     // display your accelerator         
467         NULL                             // pointer to extension record      
468       },
469       // Composite Class Part :
470       {
471         XtInheritGeometryManager,   // geometry manager for children   
472         XtInheritChangeManaged,     // change managed state of child   
473         XtInheritInsertChild,       // physically add child to parent  
474         XtInheritDeleteChild,       // physically remove child             
475         NULL                        // pointer to extension record     
476       },
477       // OpenGLArea :
478       {
479         NULL
480       }
481     };
482     return (WidgetClass)&s_openGLAreaClassRec;
483   }
484 };
485 
486 }}
487 
488 
489 #endif