1/*
2 * (c) Copyright 1993, Silicon Graphics, Inc.
3 * ALL RIGHTS RESERVED
4 * Permission to use, copy, modify, and distribute this software for
5 * any purpose and without fee is hereby granted, provided that the above
6 * copyright notice appear in all copies and that both the copyright notice
7 * and this permission notice appear in supporting documentation, and that
8 * the name of Silicon Graphics, Inc. not be used in advertising
9 * or publicity pertaining to distribution of the software without specific,
10 * written prior permission.
11 *
12 * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
13 * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
14 * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
15 * FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT SHALL SILICON
16 * GRAPHICS, INC.  BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
17 * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
18 * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
19 * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
20 * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC.  HAS BEEN
21 * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
22 * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
23 * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
24 *
25 *
26 * US Government Users Restricted Rights
27 * Use, duplication, or disclosure by the Government is subject to
28 * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
29 * (c)(1)(ii) of the Rights in Technical Data and Computer Software
30 * clause at DFARS 252.227-7013 and/or in similar or successor
31 * clauses in the FAR or the DOD or NASA FAR Supplement.
32 * Unpublished-- rights reserved under the copyright laws of the
33 * United States.  Contractor/manufacturer is Silicon Graphics,
34 * Inc., 2011 N.  Shoreline Blvd., Mountain View, CA 94039-7311.
35 *
36 * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
37 */
38
39/*
40 *
41 * This file has been slightly modified from the original for use with Mesa
42 *
43 *     Jeroen van der Zijp
44 *
45 *     jvz@cyberia.cfdrc.com
46 *
47 */
48#include <X11/IntrinsicP.h>
49#include <X11/StringDefs.h>
50#include <GL/glx.h>
51#include <GL/gl.h>
52#ifdef __GLX_MOTIF
53#include <Xm/PrimitiveP.h>
54#include "GLwMDrawAP.h"
55#else
56#include "GLwDrawAP.h"
57#endif
58#include <assert.h>
59#include <stdio.h>
60
61#ifdef __GLX_MOTIF
62#define GLwDrawingAreaWidget             GLwMDrawingAreaWidget
63#define GLwDrawingAreaClassRec           GLwMDrawingAreaClassRec
64#define glwDrawingAreaClassRec           glwMDrawingAreaClassRec
65#define glwDrawingAreaWidgetClass        glwMDrawingAreaWidgetClass
66#define GLwDrawingAreaRec                GLwMDrawingAreaRec
67#endif
68
69#define ATTRIBLIST_SIZE 32
70
71#define offset(field) XtOffset(GLwDrawingAreaWidget,glwDrawingArea.field)
72
73
74/* forward definitions */
75static void createColormap(GLwDrawingAreaWidget w,int offset,XrmValue *value);
76static void Initialize(GLwDrawingAreaWidget req,GLwDrawingAreaWidget neww,ArgList args,Cardinal *num_args);
77static void Realize(Widget w,Mask *valueMask,XSetWindowAttributes *attributes);
78static void Redraw(GLwDrawingAreaWidget w,XEvent *event,Region region);
79static void Resize(GLwDrawingAreaWidget glw);
80static void Destroy(GLwDrawingAreaWidget glw);
81static void glwInput(GLwDrawingAreaWidget glw,XEvent *event,String *params,Cardinal *numParams);
82
83
84
85static char defaultTranslations[] =
86#ifdef __GLX_MOTIF
87     "<Key>osfHelp:PrimitiveHelp() \n"
88#endif
89    "<KeyDown>:   glwInput() \n\
90     <KeyUp>:     glwInput() \n\
91     <BtnDown>:   glwInput() \n\
92     <BtnUp>:     glwInput() \n\
93     <BtnMotion>: glwInput() ";
94
95
96static XtActionsRec actions[] = {
97  {"glwInput",(XtActionProc)glwInput},                /* key or mouse input */
98  };
99
100
101/*
102 * There is a bit of unusual handling of the resources here.
103 * Because Xt insists on allocating the colormap resource when it is
104 * processing the core resources (even if we redeclare the colormap
105 * resource here, we need to do a little trick.  When Xt first allocates
106 * the colormap, we allow it to allocate the default one, since we have
107 * not yet determined the appropriate visual (which is determined from
108 * resources parsed after the colormap).  We also let it allocate colors
109 * in that default colormap.
110 *
111 * In the initialize proc we calculate the actual visual.  Then, we
112 * reobtain the colormap resource using XtGetApplicationResources in
113 * the initialize proc.  If requested, we also reallocate colors in
114 * that colormap using the same method.
115 */
116
117static XtResource resources[] = {
118  /* The GLX attributes.  Add any new attributes here */
119
120  {GLwNbufferSize, GLwCBufferSize, XtRInt, sizeof (int),
121       offset(bufferSize), XtRImmediate, (XtPointer) 0},
122
123  {GLwNlevel, GLwCLevel, XtRInt, sizeof (int),
124       offset(level), XtRImmediate, (XtPointer) 0},
125
126  {GLwNrgba, GLwCRgba, XtRBoolean, sizeof (Boolean),
127       offset(rgba), XtRImmediate, (XtPointer) FALSE},
128
129  {GLwNdoublebuffer, GLwCDoublebuffer, XtRBoolean, sizeof (Boolean),
130       offset(doublebuffer), XtRImmediate, (XtPointer) FALSE},
131
132  {GLwNstereo, GLwCStereo, XtRBoolean, sizeof (Boolean),
133       offset(stereo), XtRImmediate, (XtPointer) FALSE},
134
135  {GLwNauxBuffers, GLwCAuxBuffers, XtRInt, sizeof (int),
136       offset(auxBuffers), XtRImmediate, (XtPointer) 0},
137
138  {GLwNredSize, GLwCColorSize, XtRInt, sizeof (int),
139       offset(redSize), XtRImmediate, (XtPointer) 1},
140
141  {GLwNgreenSize, GLwCColorSize, XtRInt, sizeof (int),
142       offset(greenSize), XtRImmediate, (XtPointer) 1},
143
144  {GLwNblueSize, GLwCColorSize, XtRInt, sizeof (int),
145       offset(blueSize), XtRImmediate, (XtPointer) 1},
146
147  {GLwNalphaSize, GLwCAlphaSize, XtRInt, sizeof (int),
148       offset(alphaSize), XtRImmediate, (XtPointer) 0},
149
150  {GLwNdepthSize, GLwCDepthSize, XtRInt, sizeof (int),
151       offset(depthSize), XtRImmediate, (XtPointer) 0},
152
153  {GLwNstencilSize, GLwCStencilSize, XtRInt, sizeof (int),
154       offset(stencilSize), XtRImmediate, (XtPointer) 0},
155
156  {GLwNaccumRedSize, GLwCAccumColorSize, XtRInt, sizeof (int),
157       offset(accumRedSize), XtRImmediate, (XtPointer) 0},
158
159  {GLwNaccumGreenSize, GLwCAccumColorSize, XtRInt, sizeof (int),
160       offset(accumGreenSize), XtRImmediate, (XtPointer) 0},
161
162  {GLwNaccumBlueSize, GLwCAccumColorSize, XtRInt, sizeof (int),
163       offset(accumBlueSize), XtRImmediate, (XtPointer) 0},
164
165  {GLwNaccumAlphaSize, GLwCAccumAlphaSize, XtRInt, sizeof (int),
166       offset(accumAlphaSize), XtRImmediate, (XtPointer) 0},
167
168  /* the attribute list */
169  {GLwNattribList, GLwCAttribList, XtRPointer, sizeof(int *),
170       offset(attribList), XtRImmediate, (XtPointer) NULL},
171
172  /* the visual info */
173  {GLwNvisualInfo, GLwCVisualInfo, GLwRVisualInfo, sizeof (XVisualInfo *),
174       offset(visualInfo), XtRImmediate, (XtPointer) NULL},
175
176  /* miscellaneous resources */
177  {GLwNinstallColormap, GLwCInstallColormap, XtRBoolean, sizeof (Boolean),
178       offset(installColormap), XtRImmediate, (XtPointer) TRUE},
179
180  {GLwNallocateBackground, GLwCAllocateColors, XtRBoolean, sizeof (Boolean),
181       offset(allocateBackground), XtRImmediate, (XtPointer) FALSE},
182
183  {GLwNallocateOtherColors, GLwCAllocateColors, XtRBoolean, sizeof (Boolean),
184       offset(allocateOtherColors), XtRImmediate, (XtPointer) FALSE},
185
186  {GLwNinstallBackground, GLwCInstallBackground, XtRBoolean, sizeof (Boolean),
187       offset(installBackground), XtRImmediate, (XtPointer) TRUE},
188
189  {GLwNginitCallback, GLwCCallback, XtRCallback, sizeof (XtCallbackList),
190       offset(ginitCallback), XtRImmediate, (XtPointer) NULL},
191
192  {GLwNinputCallback, GLwCCallback, XtRCallback, sizeof (XtCallbackList),
193       offset(inputCallback), XtRImmediate, (XtPointer) NULL},
194
195  {GLwNresizeCallback, GLwCCallback, XtRCallback, sizeof (XtCallbackList),
196       offset(resizeCallback), XtRImmediate, (XtPointer) NULL},
197
198  {GLwNexposeCallback, GLwCCallback, XtRCallback, sizeof (XtCallbackList),
199       offset(exposeCallback), XtRImmediate, (XtPointer) NULL},
200
201  /* Changes to Motif primitive resources */
202#ifdef __GLX_MOTIF
203  {XmNtraversalOn, XmCTraversalOn, XmRBoolean, sizeof (Boolean),
204   XtOffset (GLwDrawingAreaWidget, primitive.traversal_on), XmRImmediate,
205   (XtPointer)FALSE},
206
207  /* highlighting is normally disabled, as when Motif tries to disable
208   * highlighting, it tries to reset the color back to the parent's
209   * background (usually Motif blue).  Unfortunately, that is in a
210   * different colormap, and doesn't work too well.
211   */
212  {XmNhighlightOnEnter, XmCHighlightOnEnter, XmRBoolean, sizeof (Boolean),
213   XtOffset (GLwDrawingAreaWidget, primitive.highlight_on_enter),
214   XmRImmediate, (XtPointer) FALSE},
215
216  {XmNhighlightThickness, XmCHighlightThickness, XmRHorizontalDimension,
217   sizeof (Dimension),
218   XtOffset (GLwDrawingAreaWidget, primitive.highlight_thickness),
219   XmRImmediate, (XtPointer) 0},
220#endif
221  };
222
223
224/*
225** The following resources are reobtained using XtGetApplicationResources
226** in the initialize proc.
227*/
228
229/* The colormap */
230static XtResource initializeResources[] = {
231  /* reobtain the colormap with the new visual */
232  {XtNcolormap, XtCColormap, XtRColormap, sizeof(Colormap),
233   XtOffset(GLwDrawingAreaWidget, core.colormap),
234   XtRCallProc,(XtPointer) createColormap},
235  };
236
237
238/* reallocate any colors we need in the new colormap */
239
240/* The background is obtained only if the allocateBackground resource is TRUE*/
241static XtResource backgroundResources[] = {
242#ifdef __GLX_MOTIF
243  {XmNbackground, XmCBackground,XmRPixel,
244   sizeof(Pixel),XtOffset(GLwDrawingAreaWidget,core.background_pixel),
245   XmRString,(XtPointer)"lightgrey"},
246   /*XmRCallProc,(XtPointer)_XmBackgroundColorDefault},*/
247
248  {XmNbackgroundPixmap,XmCPixmap,XmRXmBackgroundPixmap,
249   sizeof(Pixmap),XtOffset(GLwDrawingAreaWidget,core.background_pixmap),
250   XmRImmediate,(XtPointer)XmUNSPECIFIED_PIXMAP},
251
252#else
253  {XtNbackground,XtCBackground,XtRPixel,sizeof(Pixel),
254   XtOffset(GLwDrawingAreaWidget,core.background_pixel),
255   XtRString,(XtPointer)"lightgrey"},
256   /*XtRString,(XtPointer)"XtDefaultBackground"},*/
257
258  {XtNbackgroundPixmap, XtCPixmap, XtRPixmap, sizeof(Pixmap),
259   XtOffset(GLwDrawingAreaWidget,core.background_pixmap),
260   XtRImmediate,(XtPointer)XtUnspecifiedPixmap},
261#endif
262  };
263
264
265
266/* The other colors such as the foreground are allocated only if
267 * allocateOtherColors are set.  These resources only exist in Motif.
268 */
269#ifdef __GLX_MOTIF
270static XtResource otherColorResources[] = {
271  {XmNforeground,XmCForeground,XmRPixel,
272   sizeof(Pixel),XtOffset(GLwDrawingAreaWidget,primitive.foreground),
273   XmRString,(XtPointer)"lightgrey"},
274   /*XmRCallProc, (XtPointer) _XmForegroundColorDefault},*/
275
276  {XmNhighlightColor,XmCHighlightColor,XmRPixel,sizeof(Pixel),
277   XtOffset(GLwDrawingAreaWidget,primitive.highlight_color),
278   XmRString,(XtPointer)"lightgrey"},
279   /*XmRCallProc,(XtPointer)_XmHighlightColorDefault},*/
280
281  {XmNhighlightPixmap,XmCHighlightPixmap,XmRPrimHighlightPixmap,
282   sizeof(Pixmap),
283   XtOffset(GLwDrawingAreaWidget,primitive.highlight_pixmap),
284   XmRImmediate,(XtPointer)XmUNSPECIFIED_PIXMAP},
285   /*XmRCallProc,(XtPointer)_XmPrimitiveHighlightPixmapDefault},*/
286  };
287#endif
288
289
290#undef offset
291
292
293GLwDrawingAreaClassRec glwDrawingAreaClassRec = {
294  { /* core fields */
295#ifdef __GLX_MOTIF
296    /* superclass                */        (WidgetClass) &xmPrimitiveClassRec,
297    /* class_name                */        "GLwMDrawingArea",
298#else /* not __GLX_MOTIF */
299    /* superclass                */        (WidgetClass) &widgetClassRec,
300    /* class_name                */        "GLwDrawingArea",
301#endif /* __GLX_MOTIF */
302    /* widget_size               */        sizeof(GLwDrawingAreaRec),
303    /* class_initialize          */        NULL,
304    /* class_part_initialize     */        NULL,
305    /* class_inited              */        FALSE,
306    /* initialize                */        (XtInitProc) Initialize,
307    /* initialize_hook           */        NULL,
308    /* realize                   */        Realize,
309    /* actions                   */        actions,
310    /* num_actions               */        XtNumber(actions),
311    /* resources                 */        resources,
312    /* num_resources             */        XtNumber(resources),
313    /* xrm_class                 */        NULLQUARK,
314    /* compress_motion           */        TRUE,
315    /* compress_exposure         */        TRUE,
316    /* compress_enterleave       */        TRUE,
317    /* visible_interest          */        TRUE,
318    /* destroy                   */        (XtWidgetProc) Destroy,
319    /* resize                    */        (XtWidgetProc) Resize,
320    /* expose                    */        (XtExposeProc) Redraw,
321    /* set_values                */        NULL,
322    /* set_values_hook           */        NULL,
323    /* set_values_almost         */        XtInheritSetValuesAlmost,
324    /* get_values_hook           */        NULL,
325    /* accept_focus              */        NULL,
326    /* version                   */        XtVersion,
327    /* callback_private          */        NULL,
328    /* tm_table                  */        defaultTranslations,
329    /* query_geometry            */        XtInheritQueryGeometry,
330    /* display_accelerator       */        XtInheritDisplayAccelerator,
331    /* extension                 */        NULL
332  },
333#ifdef __GLX_MOTIF /* primitive resources */
334  {
335    /* border_highlight          */        XmInheritBorderHighlight,
336    /* border_unhighlight        */        XmInheritBorderUnhighlight,
337    /* translations              */        XtInheritTranslations,
338    /* arm_and_activate          */        NULL,
339    /* get_resources             */        NULL,
340    /* num get_resources         */        0,
341    /* extension                 */        NULL,
342  }
343#endif
344  };
345
346WidgetClass glwDrawingAreaWidgetClass=(WidgetClass)&glwDrawingAreaClassRec;
347
348
349
350static void error(Widget w,char* string){
351  char buf[100];
352#ifdef __GLX_MOTIF
353  sprintf(buf,"GLwMDrawingArea: %s\n",string);
354#else
355  sprintf(buf,"GLwDrawingArea: %s\n",string);
356#endif
357  XtAppError(XtWidgetToApplicationContext(w),buf);
358  }
359
360
361static void warning(Widget w,char* string){
362  char buf[100];
363#ifdef __GLX_MOTIF
364  sprintf (buf, "GLwMDraw: %s\n", string);
365#else
366  sprintf (buf, "GLwDraw: %s\n", string);
367#endif
368  XtAppWarning(XtWidgetToApplicationContext(w), buf);
369  }
370
371
372
373/* Initialize the attribList based on the attributes */
374static void createAttribList(GLwDrawingAreaWidget w){
375  int *ptr;
376  w->glwDrawingArea.attribList = (int*)XtMalloc(ATTRIBLIST_SIZE*sizeof(int));
377  if(!w->glwDrawingArea.attribList){
378    error((Widget)w,"Unable to allocate attribute list");
379    }
380  ptr = w->glwDrawingArea.attribList;
381  *ptr++ = GLX_BUFFER_SIZE;
382  *ptr++ = w->glwDrawingArea.bufferSize;
383  *ptr++ = GLX_LEVEL;
384  *ptr++ = w->glwDrawingArea.level;
385  if(w->glwDrawingArea.rgba) *ptr++ = GLX_RGBA;
386  if(w->glwDrawingArea.doublebuffer) *ptr++ = GLX_DOUBLEBUFFER;
387  if(w->glwDrawingArea.stereo) *ptr++ = GLX_STEREO;
388  *ptr++ = GLX_AUX_BUFFERS;
389  *ptr++ = w->glwDrawingArea.auxBuffers;
390  *ptr++ = GLX_RED_SIZE;
391  *ptr++ = w->glwDrawingArea.redSize;
392  *ptr++ = GLX_GREEN_SIZE;
393  *ptr++ = w->glwDrawingArea.greenSize;
394  *ptr++ = GLX_BLUE_SIZE;
395  *ptr++ = w->glwDrawingArea.blueSize;
396  *ptr++ = GLX_ALPHA_SIZE;
397  *ptr++ = w->glwDrawingArea.alphaSize;
398  *ptr++ = GLX_DEPTH_SIZE;
399  *ptr++ = w->glwDrawingArea.depthSize;
400  *ptr++ = GLX_STENCIL_SIZE;
401  *ptr++ = w->glwDrawingArea.stencilSize;
402  *ptr++ = GLX_ACCUM_RED_SIZE;
403  *ptr++ = w->glwDrawingArea.accumRedSize;
404  *ptr++ = GLX_ACCUM_GREEN_SIZE;
405  *ptr++ = w->glwDrawingArea.accumGreenSize;
406  *ptr++ = GLX_ACCUM_BLUE_SIZE;
407  *ptr++ = w->glwDrawingArea.accumBlueSize;
408  *ptr++ = GLX_ACCUM_ALPHA_SIZE;
409  *ptr++ = w->glwDrawingArea.accumAlphaSize;
410  *ptr++ = None;
411  assert((ptr-w->glwDrawingArea.attribList)<ATTRIBLIST_SIZE);
412  }
413
414
415
416/* Initialize the visualInfo based on the attribute list */
417static void createVisualInfo(GLwDrawingAreaWidget w){
418  assert(w->glwDrawingArea.attribList);
419  w->glwDrawingArea.visualInfo=glXChooseVisual(XtDisplay(w),XScreenNumberOfScreen(XtScreen(w)),w->glwDrawingArea.attribList);
420  if(!w->glwDrawingArea.visualInfo) error((Widget)w,"requested visual not supported");
421  }
422
423
424
425/* Initialize the colormap based on the visual info.
426 * This routine maintains a cache of visual-infos to colormaps.  If two
427 * widgets share the same visual info, they share the same colormap.
428 * This function is called by the callProc of the colormap resource entry.
429 */
430static void createColormap(GLwDrawingAreaWidget w,int offset,XrmValue *value){
431  static struct cmapCache { Visual *visual; Colormap cmap; } *cmapCache;
432  static int cacheEntries=0;
433  static int cacheMalloced=0;
434  register int i;
435
436  assert(w->glwDrawingArea.visualInfo);
437
438  /* see if we can find it in the cache */
439  for(i=0; i<cacheEntries; i++){
440    if(cmapCache[i].visual==w->glwDrawingArea.visualInfo->visual){
441      value->addr=(XtPointer)(&cmapCache[i].cmap);
442      return;
443      }
444    }
445
446  /* not in the cache, create a new entry */
447  if(cacheEntries >= cacheMalloced){
448    /* need to malloc a new one.  Since we are likely to have only a
449     * few colormaps, we allocate one the first time, and double
450     * each subsequent time.
451     */
452    if(cacheMalloced==0){
453      cacheMalloced=1;
454      cmapCache=(struct cmapCache*)XtMalloc(sizeof(struct cmapCache));
455      }
456    else{
457      cacheMalloced<<=1;
458      cmapCache=(struct cmapCache*)XtRealloc((char*)cmapCache,sizeof(struct cmapCache)*cacheMalloced);
459      }
460    }
461
462  cmapCache[cacheEntries].cmap=XCreateColormap(XtDisplay(w),
463                                               RootWindow(XtDisplay(w),
464                                               w->glwDrawingArea.visualInfo->screen),
465                                               w->glwDrawingArea.visualInfo->visual,
466                                               AllocNone);
467  cmapCache[cacheEntries].visual=w->glwDrawingArea.visualInfo->visual;
468  value->addr=(XtPointer)(&cmapCache[cacheEntries++].cmap);
469  }
470
471
472
473static void Initialize(GLwDrawingAreaWidget req,GLwDrawingAreaWidget neww,ArgList args,Cardinal *num_args){
474
475  /* fix size */
476  if(req->core.width==0) neww->core.width=100;
477  if(req->core.height==0) neww->core.width=100;
478
479  /* create the attribute list if needed */
480  neww->glwDrawingArea.myList=FALSE;
481  if(neww->glwDrawingArea.attribList==NULL){
482    neww->glwDrawingArea.myList=TRUE;
483    createAttribList(neww);
484    }
485
486  /* Gotta have it */
487  assert(neww->glwDrawingArea.attribList);
488
489  /* determine the visual info if needed */
490  neww->glwDrawingArea.myVisual=FALSE;
491  if(neww->glwDrawingArea.visualInfo==NULL){
492    neww->glwDrawingArea.myVisual=TRUE;
493    createVisualInfo(neww);
494    }
495
496  /* Gotta have that too */
497  assert(neww->glwDrawingArea.visualInfo);
498
499  neww->core.depth=neww->glwDrawingArea.visualInfo->depth;
500
501  /* Reobtain the colormap and colors in it using XtGetApplicationResources*/
502  XtGetApplicationResources((Widget)neww,neww,initializeResources,XtNumber(initializeResources),args,*num_args);
503
504  /* obtain the color resources if appropriate */
505  if(req->glwDrawingArea.allocateBackground){
506    XtGetApplicationResources((Widget)neww,neww,backgroundResources,XtNumber(backgroundResources),args,*num_args);
507    }
508
509#ifdef __GLX_MOTIF
510  if(req->glwDrawingArea.allocateOtherColors){
511    XtGetApplicationResources((Widget)neww,neww,otherColorResources,XtNumber(otherColorResources),args,*num_args);
512    }
513#endif
514  }
515
516
517
518static void Realize(Widget w,Mask *valueMask,XSetWindowAttributes *attributes){
519  register GLwDrawingAreaWidget glw=(GLwDrawingAreaWidget)w;
520  GLwDrawingAreaCallbackStruct cb;
521  Widget parentShell;
522  Status status;
523  Window windows[2],*windowsReturn,*windowList;
524  int countReturn,i;
525
526  /* if we haven't requested that the background be both installed and
527   * allocated, don't install it.
528   */
529  if(!(glw->glwDrawingArea.installBackground && glw->glwDrawingArea.allocateBackground)){
530    *valueMask&=~CWBackPixel;
531    }
532
533  XtCreateWindow(w,(unsigned int)InputOutput,glw->glwDrawingArea.visualInfo->visual,*valueMask,attributes);
534
535  /* if appropriate, call XSetWMColormapWindows to install the colormap */
536  if(glw->glwDrawingArea.installColormap){
537
538    /* Get parent shell */
539    for(parentShell=XtParent(w); parentShell&&!XtIsShell(parentShell); parentShell=XtParent(parentShell));
540
541    if(parentShell && XtWindow(parentShell)){
542
543      /* check to see if there is already a property */
544      status=XGetWMColormapWindows(XtDisplay(parentShell),XtWindow(parentShell),&windowsReturn,&countReturn);
545
546      /* if no property, just create one */
547      if(!status){
548        windows[0]=XtWindow(w);
549        windows[1]=XtWindow(parentShell);
550        XSetWMColormapWindows(XtDisplay(parentShell),XtWindow(parentShell),windows,2);
551        }
552
553      /* there was a property, add myself to the beginning */
554      else{
555        windowList=(Window *)XtMalloc((sizeof(Window))*(countReturn+1));
556        windowList[0]=XtWindow(w);
557        for(i=0; i<countReturn; i++) windowList[i+1]=windowsReturn[i];
558        XSetWMColormapWindows(XtDisplay(parentShell),XtWindow(parentShell),windowList,countReturn+1);
559        XtFree((char*)windowList);
560        XtFree((char*)windowsReturn);
561        }
562      }
563    else{
564      warning(w,"Could not set colormap property on parent shell");
565      }
566    }
567
568  /* Invoke callbacks */
569  cb.reason=GLwCR_GINIT;
570  cb.event=NULL;
571  cb.width=glw->core.width;
572  cb.height=glw->core.height;
573  XtCallCallbackList((Widget)glw,glw->glwDrawingArea.ginitCallback,&cb);
574  }
575
576
577
578static void Redraw(GLwDrawingAreaWidget w,XEvent *event,Region region){
579  GLwDrawingAreaCallbackStruct cb;
580  if(!XtIsRealized((Widget)w)) return;
581  cb.reason=GLwCR_EXPOSE;
582  cb.event=event;
583  cb.width=w->core.width;
584  cb.height=w->core.height;
585  XtCallCallbackList((Widget)w,w->glwDrawingArea.exposeCallback,&cb);
586  }
587
588
589
590static void Resize(GLwDrawingAreaWidget glw){
591  GLwDrawingAreaCallbackStruct cb;
592  if(!XtIsRealized((Widget)glw)) return;
593  cb.reason=GLwCR_RESIZE;
594  cb.event=NULL;
595  cb.width=glw->core.width;
596  cb.height=glw->core.height;
597  XtCallCallbackList((Widget)glw,glw->glwDrawingArea.resizeCallback,&cb);
598  }
599
600
601
602static void Destroy(GLwDrawingAreaWidget glw){
603  Window *windowsReturn;
604  Widget parentShell;
605  Status status;
606  int countReturn;
607  register int i;
608
609  if(glw->glwDrawingArea.myList && glw->glwDrawingArea.attribList){
610    XtFree((XtPointer)glw->glwDrawingArea.attribList);
611    }
612
613  if(glw->glwDrawingArea.myVisual && glw->glwDrawingArea.visualInfo){
614    XtFree((XtPointer)glw->glwDrawingArea.visualInfo);
615    }
616
617  /* if my colormap was installed, remove it */
618  if(glw->glwDrawingArea.installColormap){
619
620    /* Get parent shell */
621    for(parentShell=XtParent(glw); parentShell&&!XtIsShell(parentShell); parentShell=XtParent(parentShell));
622
623    if(parentShell && XtWindow(parentShell)){
624
625      /* make sure there is a property */
626      status=XGetWMColormapWindows(XtDisplay(parentShell),XtWindow(parentShell),&windowsReturn,&countReturn);
627
628      /* if no property, just return.  If there was a property, continue */
629      if(status){
630
631        /* search for a match */
632        for(i=0; i<countReturn; i++){
633          if(windowsReturn[i]==XtWindow(glw)){
634
635            /* we found a match, now copy the rest down */
636            for(i++; i<countReturn; i++){ windowsReturn[i-1]=windowsReturn[i]; }
637
638            XSetWMColormapWindows(XtDisplay(parentShell),XtWindow(parentShell),windowsReturn,countReturn-1);
639            break;
640            }
641          }
642        XtFree((char *)windowsReturn);
643        }
644      }
645    }
646  }
647
648
649
650/* Action routine for keyboard and mouse events */
651static void glwInput(GLwDrawingAreaWidget glw,XEvent *event,String *params,Cardinal *numParams){
652  GLwDrawingAreaCallbackStruct cb;
653  cb.reason=GLwCR_INPUT;
654  cb.event=event;
655  cb.width=glw->core.width;
656  cb.height=glw->core.height;
657  XtCallCallbackList((Widget)glw,glw->glwDrawingArea.inputCallback,&cb);
658  }
659
660
661#ifdef __GLX_MOTIF
662
663/* Create routine */
664Widget GLwCreateMDrawingArea(Widget parent, char *name,ArgList arglist,Cardinal argcount){
665  return XtCreateWidget(name,glwMDrawingAreaWidgetClass, parent, arglist,argcount);
666  }
667
668#endif
669
670
671#ifndef __GLX_MOTIF
672
673/* Make context current */
674void GLwDrawingAreaMakeCurrent(Widget w,GLXContext ctx){
675  glXMakeCurrent(XtDisplay(w),XtWindow(w),ctx);
676  }
677
678
679/* Swap buffers convenience function */
680void GLwDrawingAreaSwapBuffers(Widget w){
681  glXSwapBuffers(XtDisplay(w),XtWindow(w));
682  }
683
684#endif
685