#include <X11/IntrinsicP.h>
#include <X11/StringDefs.h>
#include <GL/glx.h>
#include <GL/gl.h>
#ifdef __GLX_MOTIF
#include <Xm/PrimitiveP.h>
#include "GLwMDrawAP.h"
#else
#include "GLwDrawAP.h"
#endif
#include <assert.h>
#include <stdio.h>
#ifdef __GLX_MOTIF
#define GLwDrawingAreaWidget GLwMDrawingAreaWidget
#define GLwDrawingAreaClassRec GLwMDrawingAreaClassRec
#define glwDrawingAreaClassRec glwMDrawingAreaClassRec
#define glwDrawingAreaWidgetClass glwMDrawingAreaWidgetClass
#define GLwDrawingAreaRec GLwMDrawingAreaRec
#endif
#define ATTRIBLIST_SIZE 32
#define offset(field) XtOffset(GLwDrawingAreaWidget,glwDrawingArea.field)
static void createColormap(GLwDrawingAreaWidget w,int offset,XrmValue *value);
static void Initialize(GLwDrawingAreaWidget req,GLwDrawingAreaWidget neww,ArgList args,Cardinal *num_args);
static void Realize(Widget w,Mask *valueMask,XSetWindowAttributes *attributes);
static void Redraw(GLwDrawingAreaWidget w,XEvent *event,Region region);
static void Resize(GLwDrawingAreaWidget glw);
static void Destroy(GLwDrawingAreaWidget glw);
static void glwInput(GLwDrawingAreaWidget glw,XEvent *event,String *params,Cardinal *numParams);
static char defaultTranslations[] =
#ifdef __GLX_MOTIF
"<Key>osfHelp:PrimitiveHelp() \n"
#endif
"<KeyDown>: glwInput() \n\
<KeyUp>: glwInput() \n\
<BtnDown>: glwInput() \n\
<BtnUp>: glwInput() \n\
<BtnMotion>: glwInput() ";
static XtActionsRec actions[] = {
{"glwInput",(XtActionProc)glwInput},
};
static XtResource resources[] = {
{GLwNbufferSize, GLwCBufferSize, XtRInt, sizeof (int),
offset(bufferSize), XtRImmediate, (XtPointer) 0},
{GLwNlevel, GLwCLevel, XtRInt, sizeof (int),
offset(level), XtRImmediate, (XtPointer) 0},
{GLwNrgba, GLwCRgba, XtRBoolean, sizeof (Boolean),
offset(rgba), XtRImmediate, (XtPointer) FALSE},
{GLwNdoublebuffer, GLwCDoublebuffer, XtRBoolean, sizeof (Boolean),
offset(doublebuffer), XtRImmediate, (XtPointer) FALSE},
{GLwNstereo, GLwCStereo, XtRBoolean, sizeof (Boolean),
offset(stereo), XtRImmediate, (XtPointer) FALSE},
{GLwNauxBuffers, GLwCAuxBuffers, XtRInt, sizeof (int),
offset(auxBuffers), XtRImmediate, (XtPointer) 0},
{GLwNredSize, GLwCColorSize, XtRInt, sizeof (int),
offset(redSize), XtRImmediate, (XtPointer) 1},
{GLwNgreenSize, GLwCColorSize, XtRInt, sizeof (int),
offset(greenSize), XtRImmediate, (XtPointer) 1},
{GLwNblueSize, GLwCColorSize, XtRInt, sizeof (int),
offset(blueSize), XtRImmediate, (XtPointer) 1},
{GLwNalphaSize, GLwCAlphaSize, XtRInt, sizeof (int),
offset(alphaSize), XtRImmediate, (XtPointer) 0},
{GLwNdepthSize, GLwCDepthSize, XtRInt, sizeof (int),
offset(depthSize), XtRImmediate, (XtPointer) 0},
{GLwNstencilSize, GLwCStencilSize, XtRInt, sizeof (int),
offset(stencilSize), XtRImmediate, (XtPointer) 0},
{GLwNaccumRedSize, GLwCAccumColorSize, XtRInt, sizeof (int),
offset(accumRedSize), XtRImmediate, (XtPointer) 0},
{GLwNaccumGreenSize, GLwCAccumColorSize, XtRInt, sizeof (int),
offset(accumGreenSize), XtRImmediate, (XtPointer) 0},
{GLwNaccumBlueSize, GLwCAccumColorSize, XtRInt, sizeof (int),
offset(accumBlueSize), XtRImmediate, (XtPointer) 0},
{GLwNaccumAlphaSize, GLwCAccumAlphaSize, XtRInt, sizeof (int),
offset(accumAlphaSize), XtRImmediate, (XtPointer) 0},
{GLwNattribList, GLwCAttribList, XtRPointer, sizeof(int *),
offset(attribList), XtRImmediate, (XtPointer) NULL},
{GLwNvisualInfo, GLwCVisualInfo, GLwRVisualInfo, sizeof (XVisualInfo *),
offset(visualInfo), XtRImmediate, (XtPointer) NULL},
{GLwNinstallColormap, GLwCInstallColormap, XtRBoolean, sizeof (Boolean),
offset(installColormap), XtRImmediate, (XtPointer) TRUE},
{GLwNallocateBackground, GLwCAllocateColors, XtRBoolean, sizeof (Boolean),
offset(allocateBackground), XtRImmediate, (XtPointer) FALSE},
{GLwNallocateOtherColors, GLwCAllocateColors, XtRBoolean, sizeof (Boolean),
offset(allocateOtherColors), XtRImmediate, (XtPointer) FALSE},
{GLwNinstallBackground, GLwCInstallBackground, XtRBoolean, sizeof (Boolean),
offset(installBackground), XtRImmediate, (XtPointer) TRUE},
{GLwNginitCallback, GLwCCallback, XtRCallback, sizeof (XtCallbackList),
offset(ginitCallback), XtRImmediate, (XtPointer) NULL},
{GLwNinputCallback, GLwCCallback, XtRCallback, sizeof (XtCallbackList),
offset(inputCallback), XtRImmediate, (XtPointer) NULL},
{GLwNresizeCallback, GLwCCallback, XtRCallback, sizeof (XtCallbackList),
offset(resizeCallback), XtRImmediate, (XtPointer) NULL},
{GLwNexposeCallback, GLwCCallback, XtRCallback, sizeof (XtCallbackList),
offset(exposeCallback), XtRImmediate, (XtPointer) NULL},
#ifdef __GLX_MOTIF
{XmNtraversalOn, XmCTraversalOn, XmRBoolean, sizeof (Boolean),
XtOffset (GLwDrawingAreaWidget, primitive.traversal_on), XmRImmediate,
(XtPointer)FALSE},
{XmNhighlightOnEnter, XmCHighlightOnEnter, XmRBoolean, sizeof (Boolean),
XtOffset (GLwDrawingAreaWidget, primitive.highlight_on_enter),
XmRImmediate, (XtPointer) FALSE},
{XmNhighlightThickness, XmCHighlightThickness, XmRHorizontalDimension,
sizeof (Dimension),
XtOffset (GLwDrawingAreaWidget, primitive.highlight_thickness),
XmRImmediate, (XtPointer) 0},
#endif
};
static XtResource initializeResources[] = {
{XtNcolormap, XtCColormap, XtRColormap, sizeof(Colormap),
XtOffset(GLwDrawingAreaWidget, core.colormap),
XtRCallProc,(XtPointer) createColormap},
};
static XtResource backgroundResources[] = {
#ifdef __GLX_MOTIF
{XmNbackground, XmCBackground,XmRPixel,
sizeof(Pixel),XtOffset(GLwDrawingAreaWidget,core.background_pixel),
XmRString,(XtPointer)"lightgrey"},
{XmNbackgroundPixmap,XmCPixmap,XmRXmBackgroundPixmap,
sizeof(Pixmap),XtOffset(GLwDrawingAreaWidget,core.background_pixmap),
XmRImmediate,(XtPointer)XmUNSPECIFIED_PIXMAP},
#else
{XtNbackground,XtCBackground,XtRPixel,sizeof(Pixel),
XtOffset(GLwDrawingAreaWidget,core.background_pixel),
XtRString,(XtPointer)"lightgrey"},
{XtNbackgroundPixmap, XtCPixmap, XtRPixmap, sizeof(Pixmap),
XtOffset(GLwDrawingAreaWidget,core.background_pixmap),
XtRImmediate,(XtPointer)XtUnspecifiedPixmap},
#endif
};
#ifdef __GLX_MOTIF
static XtResource otherColorResources[] = {
{XmNforeground,XmCForeground,XmRPixel,
sizeof(Pixel),XtOffset(GLwDrawingAreaWidget,primitive.foreground),
XmRString,(XtPointer)"lighgrey"},
{XmNhighlightColor,XmCHighlightColor,XmRPixel,sizeof(Pixel),
XtOffset(GLwDrawingAreaWidget,primitive.highlight_color),
XmRString,(XtPointer)"lightgrey"},
{XmNhighlightPixmap,XmCHighlightPixmap,XmRPrimHighlightPixmap,
sizeof(Pixmap),
XtOffset(GLwDrawingAreaWidget,primitive.highlight_pixmap),
XmRImmediate,(XtPointer)XmUNSPECIFIED_PIXMAP},
};
#endif
#undef offset
GLwDrawingAreaClassRec glwDrawingAreaClassRec = {
{
#ifdef __GLX_MOTIF
(WidgetClass) &xmPrimitiveClassRec,
"GLwMDrawingArea",
#else
(WidgetClass) &widgetClassRec,
"GLwDrawingArea",
#endif
sizeof(GLwDrawingAreaRec),
NULL,
NULL,
FALSE,
(XtInitProc) Initialize,
NULL,
Realize,
actions,
XtNumber(actions),
resources,
XtNumber(resources),
NULLQUARK,
TRUE,
TRUE,
TRUE,
TRUE,
(XtWidgetProc) Destroy,
(XtWidgetProc) Resize,
(XtExposeProc) Redraw,
NULL,
NULL,
XtInheritSetValuesAlmost,
NULL,
NULL,
XtVersion,
NULL,
defaultTranslations,
XtInheritQueryGeometry,
XtInheritDisplayAccelerator,
NULL
},
#ifdef __GLX_MOTIF
{
XmInheritBorderHighlight,
XmInheritBorderUnhighlight,
XtInheritTranslations,
NULL,
NULL,
0,
NULL,
}
#endif
};
WidgetClass glwDrawingAreaWidgetClass=(WidgetClass)&glwDrawingAreaClassRec;
static void error(Widget w,char* string){
char buf[100];
#ifdef __GLX_MOTIF
sprintf(buf,"GLwMDrawingArea: %s\n",string);
#else
sprintf(buf,"GLwDrawingArea: %s\n",string);
#endif
XtAppError(XtWidgetToApplicationContext(w),buf);
}
static void warning(Widget w,char* string){
char buf[100];
#ifdef __GLX_MOTIF
sprintf (buf, "GLwMDraw: %s\n", string);
#else
sprintf (buf, "GLwDraw: %s\n", string);
#endif
XtAppWarning(XtWidgetToApplicationContext(w), buf);
}
static void createAttribList(GLwDrawingAreaWidget w){
int *ptr;
w->glwDrawingArea.attribList = (int*)XtMalloc(ATTRIBLIST_SIZE*sizeof(int));
if(!w->glwDrawingArea.attribList){
error((Widget)w,"Unable to allocate attribute list");
}
ptr = w->glwDrawingArea.attribList;
*ptr++ = GLX_BUFFER_SIZE;
*ptr++ = w->glwDrawingArea.bufferSize;
*ptr++ = GLX_LEVEL;
*ptr++ = w->glwDrawingArea.level;
if(w->glwDrawingArea.rgba) *ptr++ = GLX_RGBA;
if(w->glwDrawingArea.doublebuffer) *ptr++ = GLX_DOUBLEBUFFER;
if(w->glwDrawingArea.stereo) *ptr++ = GLX_STEREO;
*ptr++ = GLX_AUX_BUFFERS;
*ptr++ = w->glwDrawingArea.auxBuffers;
*ptr++ = GLX_RED_SIZE;
*ptr++ = w->glwDrawingArea.redSize;
*ptr++ = GLX_GREEN_SIZE;
*ptr++ = w->glwDrawingArea.greenSize;
*ptr++ = GLX_BLUE_SIZE;
*ptr++ = w->glwDrawingArea.blueSize;
*ptr++ = GLX_ALPHA_SIZE;
*ptr++ = w->glwDrawingArea.alphaSize;
*ptr++ = GLX_DEPTH_SIZE;
*ptr++ = w->glwDrawingArea.depthSize;
*ptr++ = GLX_STENCIL_SIZE;
*ptr++ = w->glwDrawingArea.stencilSize;
*ptr++ = GLX_ACCUM_RED_SIZE;
*ptr++ = w->glwDrawingArea.accumRedSize;
*ptr++ = GLX_ACCUM_GREEN_SIZE;
*ptr++ = w->glwDrawingArea.accumGreenSize;
*ptr++ = GLX_ACCUM_BLUE_SIZE;
*ptr++ = w->glwDrawingArea.accumBlueSize;
*ptr++ = GLX_ACCUM_ALPHA_SIZE;
*ptr++ = w->glwDrawingArea.accumAlphaSize;
*ptr++ = None;
assert((ptr-w->glwDrawingArea.attribList)<ATTRIBLIST_SIZE);
}
static void createVisualInfo(GLwDrawingAreaWidget w){
assert(w->glwDrawingArea.attribList);
w->glwDrawingArea.visualInfo=glXChooseVisual(XtDisplay(w),XScreenNumberOfScreen(XtScreen(w)),w->glwDrawingArea.attribList);
if(!w->glwDrawingArea.visualInfo) error((Widget)w,"requested visual not supported");
}
static void createColormap(GLwDrawingAreaWidget w,int offset,XrmValue *value){
static struct cmapCache { Visual *visual; Colormap cmap; } *cmapCache;
static int cacheEntries=0;
static int cacheMalloced=0;
register int i;
assert(w->glwDrawingArea.visualInfo);
for(i=0; i<cacheEntries; i++){
if(cmapCache[i].visual==w->glwDrawingArea.visualInfo->visual){
value->addr=(XtPointer)(&cmapCache[i].cmap);
return;
}
}
if(cacheEntries >= cacheMalloced){
if(cacheMalloced==0){
cacheMalloced=1;
cmapCache=(struct cmapCache*)XtMalloc(sizeof(struct cmapCache));
}
else{
cacheMalloced<<=1;
cmapCache=(struct cmapCache*)XtRealloc((char*)cmapCache,sizeof(struct cmapCache)*cacheMalloced);
}
}
cmapCache[cacheEntries].cmap=XCreateColormap(XtDisplay(w),
RootWindow(XtDisplay(w),
w->glwDrawingArea.visualInfo->screen),
w->glwDrawingArea.visualInfo->visual,
AllocNone);
cmapCache[cacheEntries].visual=w->glwDrawingArea.visualInfo->visual;
value->addr=(XtPointer)(&cmapCache[cacheEntries++].cmap);
}
static void Initialize(GLwDrawingAreaWidget req,GLwDrawingAreaWidget neww,ArgList args,Cardinal *num_args){
if(req->core.width==0) neww->core.width=100;
if(req->core.height==0) neww->core.width=100;
neww->glwDrawingArea.myList=FALSE;
if(neww->glwDrawingArea.attribList==NULL){
neww->glwDrawingArea.myList=TRUE;
createAttribList(neww);
}
assert(neww->glwDrawingArea.attribList);
neww->glwDrawingArea.myVisual=FALSE;
if(neww->glwDrawingArea.visualInfo==NULL){
neww->glwDrawingArea.myVisual=TRUE;
createVisualInfo(neww);
}
assert(neww->glwDrawingArea.visualInfo);
neww->core.depth=neww->glwDrawingArea.visualInfo->depth;
XtGetApplicationResources((Widget)neww,neww,initializeResources,XtNumber(initializeResources),args,*num_args);
if(req->glwDrawingArea.allocateBackground){
XtGetApplicationResources((Widget)neww,neww,backgroundResources,XtNumber(backgroundResources),args,*num_args);
}
#ifdef __GLX_MOTIF
if(req->glwDrawingArea.allocateOtherColors){
XtGetApplicationResources((Widget)neww,neww,otherColorResources,XtNumber(otherColorResources),args,*num_args);
}
#endif
}
static void Realize(Widget w,Mask *valueMask,XSetWindowAttributes *attributes){
register GLwDrawingAreaWidget glw=(GLwDrawingAreaWidget)w;
GLwDrawingAreaCallbackStruct cb;
Widget parentShell;
Status status;
Window windows[2],*windowsReturn,*windowList;
int countReturn,i;
if(!(glw->glwDrawingArea.installBackground && glw->glwDrawingArea.allocateBackground)){
*valueMask&=~CWBackPixel;
}
XtCreateWindow(w,(unsigned int)InputOutput,glw->glwDrawingArea.visualInfo->visual,*valueMask,attributes);
if(glw->glwDrawingArea.installColormap){
for(parentShell=XtParent(w); parentShell&&!XtIsShell(parentShell); parentShell=XtParent(parentShell));
if(parentShell && XtWindow(parentShell)){
status=XGetWMColormapWindows(XtDisplay(parentShell),XtWindow(parentShell),&windowsReturn,&countReturn);
if(!status){
windows[0]=XtWindow(w);
windows[1]=XtWindow(parentShell);
XSetWMColormapWindows(XtDisplay(parentShell),XtWindow(parentShell),windows,2);
}
else{
windowList=(Window *)XtMalloc((sizeof(Window))*(countReturn+1));
windowList[0]=XtWindow(w);
for(i=0; i<countReturn; i++) windowList[i+1]=windowsReturn[i];
XSetWMColormapWindows(XtDisplay(parentShell),XtWindow(parentShell),windowList,countReturn+1);
XtFree((char*)windowList);
XtFree((char*)windowsReturn);
}
}
else{
warning(w,"Could not set colormap property on parent shell");
}
}
cb.reason=GLwCR_GINIT;
cb.event=NULL;
cb.width=glw->core.width;
cb.height=glw->core.height;
XtCallCallbackList((Widget)glw,glw->glwDrawingArea.ginitCallback,&cb);
}
static void Redraw(GLwDrawingAreaWidget w,XEvent *event,Region region){
GLwDrawingAreaCallbackStruct cb;
if(!XtIsRealized((Widget)w)) return;
cb.reason=GLwCR_EXPOSE;
cb.event=event;
cb.width=w->core.width;
cb.height=w->core.height;
XtCallCallbackList((Widget)w,w->glwDrawingArea.exposeCallback,&cb);
}
static void Resize(GLwDrawingAreaWidget glw){
GLwDrawingAreaCallbackStruct cb;
if(!XtIsRealized((Widget)glw)) return;
cb.reason=GLwCR_RESIZE;
cb.event=NULL;
cb.width=glw->core.width;
cb.height=glw->core.height;
XtCallCallbackList((Widget)glw,glw->glwDrawingArea.resizeCallback,&cb);
}
static void Destroy(GLwDrawingAreaWidget glw){
Window *windowsReturn;
Widget parentShell;
Status status;
int countReturn;
register int i;
if(glw->glwDrawingArea.myList && glw->glwDrawingArea.attribList){
XtFree((XtPointer)glw->glwDrawingArea.attribList);
}
if(glw->glwDrawingArea.myVisual && glw->glwDrawingArea.visualInfo){
XtFree((XtPointer)glw->glwDrawingArea.visualInfo);
}
if(glw->glwDrawingArea.installColormap){
for(parentShell=XtParent(glw); parentShell&&!XtIsShell(parentShell); parentShell=XtParent(parentShell));
if(parentShell && XtWindow(parentShell)){
status=XGetWMColormapWindows(XtDisplay(parentShell),XtWindow(parentShell),&windowsReturn,&countReturn);
if(status){
for(i=0; i<countReturn; i++){
if(windowsReturn[i]==XtWindow(glw)){
for(i++; i<countReturn; i++){ windowsReturn[i-1]=windowsReturn[i]; }
XSetWMColormapWindows(XtDisplay(parentShell),XtWindow(parentShell),windowsReturn,countReturn-1);
break;
}
}
XtFree((char *)windowsReturn);
}
}
}
}
static void glwInput(GLwDrawingAreaWidget glw,XEvent *event,String *params,Cardinal *numParams){
GLwDrawingAreaCallbackStruct cb;
cb.reason=GLwCR_INPUT;
cb.event=event;
cb.width=glw->core.width;
cb.height=glw->core.height;
XtCallCallbackList((Widget)glw,glw->glwDrawingArea.inputCallback,&cb);
}
#ifdef __GLX_MOTIF
Widget GLwCreateMDrawingArea(Widget parent, char *name,ArgList arglist,Cardinal argcount){
return XtCreateWidget(name,glwMDrawingAreaWidgetClass, parent, arglist,argcount);
}
#endif
#ifndef __GLX_MOTIF
void GLwDrawingAreaMakeCurrent(Widget w,GLXContext ctx){
glXMakeCurrent(XtDisplay(w),XtWindow(w),ctx);
}
void GLwDrawingAreaSwapBuffers(Widget w){
glXSwapBuffers(XtDisplay(w),XtWindow(w));
}
#endif