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