#include <stdio.h>
#include <GL/glx.h>
#include <GL/gl.h>
#ifdef __GLX_MOTIF
#include "GLwMDrawAP.h"
#else
#include "GLwDrawAP.h"
#include <X11/IntrinsicP.h>
#include <X11/StringDefs.h>
#endif
#include <assert.h>
#ifdef __GLX_MOTIF
#define GLwDrawingAreaWidget GLwMDrawingAreaWidget
#define GLwDrawingAreaClassRec GLwMDrawingAreaClassRec
#define glwDrawingAreaClassRec glwMDrawingAreaClassRec
#define glwDrawingAreaWidgetClass glwMDrawingAreaWidgetClass
#define GLwDrawingAreaRec GLwMDrawingAreaRec
#endif
static void createColormap(GLwDrawingAreaWidget w,
int offset, XrmValue *value);
static void Initialize(GLwDrawingAreaWidget req, GLwDrawingAreaWidget new,
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);
#define offset(field) XtOffset(GLwDrawingAreaWidget, glwDrawingArea.field)
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 void glwInput(GLwDrawingAreaWidget glw, XEvent *event,
String *, Cardinal *);
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),
XmRCallProc, (XtPointer) _XmBackgroundColorDefault
},
{
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)"XtDefaultBackground"},
{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),
XmRCallProc, (XtPointer) _XmForegroundColorDefault
},
{
XmNhighlightColor, XmCHighlightColor, XmRPixel, sizeof (Pixel),
XtOffset(GLwDrawingAreaWidget, primitive.highlight_color),
XmRCallProc, (XtPointer) _XmHighlightColorDefault
},
{
XmNhighlightPixmap, XmCHighlightPixmap, XmRPrimHighlightPixmap,
sizeof (Pixmap),
XtOffset(GLwDrawingAreaWidget, primitive.highlight_pixmap),
XmRCallProc, (XtPointer) _XmPrimitiveHighlightPixmapDefault
},
};
#endif
struct attribInfo
{
int offset;
int attribute;
};
static struct attribInfo intAttribs[] =
{
{ offset(bufferSize), GLX_BUFFER_SIZE },
{ offset(level), GLX_LEVEL },
{ offset(auxBuffers), GLX_AUX_BUFFERS },
{ offset(redSize), GLX_RED_SIZE },
{ offset(greenSize), GLX_GREEN_SIZE },
{ offset(blueSize), GLX_BLUE_SIZE },
{ offset(alphaSize), GLX_ALPHA_SIZE },
{ offset(depthSize), GLX_DEPTH_SIZE },
{ offset(stencilSize), GLX_STENCIL_SIZE },
{ offset(accumRedSize), GLX_ACCUM_RED_SIZE },
{ offset(accumGreenSize), GLX_ACCUM_GREEN_SIZE },
{ offset(accumBlueSize), GLX_ACCUM_BLUE_SIZE },
{ offset(accumAlphaSize), GLX_ACCUM_ALPHA_SIZE },
{ 0, None },
};
static struct attribInfo booleanAttribs[] =
{
{ offset(rgba), GLX_RGBA },
{ offset(doublebuffer), GLX_DOUBLEBUFFER },
{ offset(stereo), GLX_STEREO },
{ 0, None },
};
#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 listLength;
register struct attribInfo *ap;
int *ip;
listLength=1;
for (ap = booleanAttribs; ap->attribute; ap++)
{
if (*(Boolean *)(((char *)w)+ap->offset))
listLength++;
}
for (ap = intAttribs; ap->attribute; ap++)
{
if (*(int *)(((char *)w)+ap->offset))
listLength+=2;
}
w->glwDrawingArea.attribList = (int *)XtMalloc(listLength*sizeof(int));
ip = w->glwDrawingArea.attribList;
for (ap = booleanAttribs; ap->attribute; ap++)
{
if (*(Boolean *)(((char *)w)+ap->offset))
*ip++ = ap->attribute;
}
for (ap = intAttribs; ap->attribute; ap++)
{
if (*(int *)(((char *)w)+ap->offset))
{
*ip++ = ap->attribute;
*ip++ = *(int *)(((char *)w)+ap->offset);
}
}
*ip = None;
}
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;
int screen;
} *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 &&
cmapCache[i].screen == w->glwDrawingArea.visualInfo->screen)
{
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;
cmapCache[cacheEntries].screen = w->glwDrawingArea.visualInfo->screen;
value->addr = (XtPointer) (&cmapCache[cacheEntries++].cmap);
}
static void
Initialize (GLwDrawingAreaWidget req, GLwDrawingAreaWidget new,
ArgList args, Cardinal *num_args)
{
if (req->core.width == 0)
new->core.width = 100;
if (req->core.height == 0)
new->core.width = 100;
if (new->glwDrawingArea.attribList == NULL)
{
new->glwDrawingArea.myList = TRUE;
createAttribList(new);
}
else
new->glwDrawingArea.myList = FALSE;
if (new->glwDrawingArea.visualInfo == NULL)
{
new->glwDrawingArea.myVisual = TRUE;
createVisualInfo(new);
}
else
new->glwDrawingArea.myVisual = FALSE;
new->core.depth = new->glwDrawingArea.visualInfo->depth;
XtGetApplicationResources((Widget) new, new,
initializeResources,
XtNumber(initializeResources),
args, *num_args);
if (req->glwDrawingArea.allocateBackground)
XtGetApplicationResources((Widget) new, new,
backgroundResources,
XtNumber(backgroundResources),
args, *num_args);
#ifdef __GLX_MOTIF
if (req->glwDrawingArea.allocateOtherColors)
XtGetApplicationResources((Widget) new, new,
otherColorResources,
XtNumber(otherColorResources),
args, *num_args);
#endif
}
static void
Realize(Widget w, Mask *valueMask, XSetWindowAttributes *attributes)
{
register GLwDrawingAreaWidget glw = (GLwDrawingAreaWidget)w;
GLwDrawingAreaCallbackStruct cb;
if (!(glw->glwDrawingArea.installBackground &&
glw->glwDrawingArea.allocateBackground))
*valueMask &= ~CWBackPixel;
XtCreateWindow (w, (unsigned int)InputOutput,
glw->glwDrawingArea.visualInfo->visual,
*valueMask, attributes);
if (glw->glwDrawingArea.installColormap)
{
Widget parentShell = XtParent(w);
Status status;
Window *windowsReturn;
int countReturn;
while (parentShell && !XtIsShell(parentShell))
parentShell = XtParent(parentShell);
if (parentShell && XtWindow(parentShell))
{
status = XGetWMColormapWindows(XtDisplay(parentShell),
XtWindow(parentShell),
&windowsReturn, &countReturn);
if (!status)
{
Window windows[2];
windows[0] = XtWindow(w);
windows[1] = XtWindow(parentShell);
XSetWMColormapWindows(XtDisplay(parentShell),
XtWindow(parentShell),
windows, 2);
}
else
{
Window *windows = (Window *)XtMalloc((sizeof(Window))*
(countReturn+1));
register int i;
windows[0] = XtWindow(w);
for (i=0; i<countReturn; i++)
windows[i+1] = windowsReturn[i];
XSetWMColormapWindows(XtDisplay(parentShell),
XtWindow(parentShell),
windows, countReturn+1);
XtFree((char *) windows);
XFree((char *) windowsReturn);
}
}
else
warning((Widget)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;
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)
{
if (glw->glwDrawingArea.myList && glw->glwDrawingArea.attribList)
XtFree ((XtPointer)glw->glwDrawingArea.attribList);
if (glw->glwDrawingArea.myVisual && glw->glwDrawingArea.visualInfo)
XFree ((XtPointer)glw->glwDrawingArea.visualInfo);
if (glw->glwDrawingArea.installColormap)
{
Widget parentShell = XtParent(glw);
Status status;
Window *windowsReturn;
int countReturn;
register int i;
while (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;
}
}
XFree((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