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  * This file has been slightly modified from the original for use with Mesa.
41  *
42  *     Jeroen van der Zijp <jvz@cyberia.cfdrc.com>
43  */
44 
45 /*
46  * This file has been heavily modified from the original.  It has been
47  * stripped down and moved into the SoXt namespace to avoid potential
48  * name-collisions with externally installed GL widgets, and all pure
49  * Xt vs. Xt/Motif ifdef wrappers have been removed (only the Motif
50  * parts remain).  You are encouraged to rather go back to the source,
51  * which you will find with Mesa, than to base your GL widget derivation
52  * on this code.
53  *
54  *     Lars J. Aas <larsa@sim.no>,
55  *     19th may 2000
56  */
57 
58 #include <assert.h>
59 #include <stdio.h>
60 
61 #include <X11/IntrinsicP.h>
62 #include <X11/StringDefs.h>
63 #include <GL/gl.h>
64 #include <Xm/PrimitiveP.h>
65 
66 #include <Inventor/errors/SoDebugError.h>
67 
68 #include <soxtdefs.h>
69 #include <Inventor/Xt/widgets/SoXtGLAreaP.h>
70 
71 #define ATTRIBLIST_SIZE 30
72 
73 // *************************************************************************
74 // forward declarations:
75 
76 static void createColormap(SoXtGLAreaWidget, int, XrmValue *);
77 static void Initialize(SoXtGLAreaWidget, SoXtGLAreaWidget,
78                         ArgList, Cardinal *);
79 static void Realize(Widget, Mask *, XSetWindowAttributes *);
80 static void Redraw(SoXtGLAreaWidget, XEvent *, Region);
81 static void Resize(SoXtGLAreaWidget);
82 static void Destroy(SoXtGLAreaWidget);
83 static void glwInput(SoXtGLAreaWidget, XEvent *, String *, Cardinal *);
84 static Boolean SoXtGLArea_set_values(Widget, Widget, Widget, ArgList, Cardinal *);
85 
86 // *************************************************************************
87 
88 static
89 char
90 SoXtGLArea_defaultTranslations[] =
91     "<Key>osfHelp:PrimitiveHelp() \n\
92      <KeyDown>:   glwInput() \n\
93      <KeyUp>:     glwInput() \n\
94      <BtnDown>:   glwInput() \n\
95      <BtnUp>:     glwInput() \n\
96      <BtnMotion>: glwInput() ";
97 
98 static
99 XtActionsRec
100 SoXtGLArea_actions[] = {
101   { "glwInput", (XtActionProc) glwInput }, // key or mouse input
102 }; // actions
103 
104 // There is a bit of unusual handling of the resources here.
105 // Because Xt insists on allocating the colormap resource when it is
106 // processing the core resources (even if we redeclare the colormap
107 // resource here, we need to do a little trick.  When Xt first allocates
108 // the colormap, we allow it to allocate the default one, since we have
109 // not yet determined the appropriate visual (which is determined from
110 // resources parsed after the colormap).  We also let it allocate colors
111 // in that default colormap.
112 //
113 // In the initialize proc we calculate the actual visual.  Then, we
114 // reobtain the colormap resource using XtGetApplicationResources in
115 // the initialize proc.  If requested, we also reallocate colors in
116 // that colormap using the same method.
117 
118 #define coffset(field) XtOffset(SoXtGLAreaWidget, core.field)
119 #define poffset(field) XtOffset(SoXtGLAreaWidget, primitive.field)
120 #define offset(field)  XtOffset(SoXtGLAreaWidget, soxtGLArea.field)
121 
122 static
123 XtResource
124 SoXtGLArea_resources[] =
125 {
126   // The GLX attributes.  Add any new attributes here
127   {
128     SoXtNbufferSize, SoXtCBufferSize, XtRInt,
129     sizeof(int), offset(bufferSize),
130     XtRImmediate, (XtPointer) 0
131   }, {
132     SoXtNlevel, SoXtCLevel, XtRInt,
133     sizeof(int), offset(level),
134     XtRImmediate, (XtPointer) 0
135   }, {
136     SoXtNrgba, SoXtCRgba, XtRBoolean,
137     sizeof(Boolean), offset(rgba),
138     XtRImmediate, (XtPointer) FALSE
139   }, {
140     SoXtNdoublebuffer, SoXtCDoublebuffer, XtRBoolean,
141     sizeof(Boolean), offset(doublebuffer),
142     XtRImmediate, (XtPointer) FALSE
143   }, {
144     SoXtNstereo, SoXtCStereo, XtRBoolean,
145     sizeof(Boolean), offset(stereo),
146     XtRImmediate, (XtPointer) FALSE
147   }, {
148     SoXtNauxBuffers, SoXtCAuxBuffers, XtRInt,
149     sizeof(int), offset(auxBuffers),
150     XtRImmediate, (XtPointer) 0
151   }, {
152     SoXtNredSize, SoXtCColorSize, XtRInt,
153     sizeof(int), offset(redSize),
154     XtRImmediate, (XtPointer) 1
155   }, {
156     SoXtNgreenSize, SoXtCColorSize, XtRInt,
157     sizeof(int), offset(greenSize),
158     XtRImmediate, (XtPointer) 1
159   }, {
160     SoXtNblueSize, SoXtCColorSize, XtRInt,
161     sizeof(int), offset(blueSize),
162     XtRImmediate, (XtPointer) 1
163   }, {
164     SoXtNalphaSize, SoXtCAlphaSize, XtRInt,
165     sizeof(int), offset(alphaSize),
166     XtRImmediate, (XtPointer) 0
167   }, {
168     SoXtNdepthSize, SoXtCDepthSize, XtRInt,
169     sizeof(int), offset(depthSize),
170     XtRImmediate, (XtPointer) 0
171   }, {
172     SoXtNstencilSize, SoXtCStencilSize, XtRInt,
173     sizeof(int), offset(stencilSize),
174     XtRImmediate, (XtPointer) 0
175   }, {
176     SoXtNaccumRedSize, SoXtCAccumColorSize, XtRInt,
177     sizeof(int), offset(accumRedSize),
178     XtRImmediate, (XtPointer) 0
179   }, {
180     SoXtNaccumGreenSize, SoXtCAccumColorSize, XtRInt,
181     sizeof(int), offset(accumGreenSize),
182     XtRImmediate, (XtPointer) 0
183   }, {
184     SoXtNaccumBlueSize, SoXtCAccumColorSize, XtRInt,
185     sizeof(int), offset(accumBlueSize),
186     XtRImmediate, (XtPointer) 0
187   }, {
188     SoXtNaccumAlphaSize, SoXtCAccumAlphaSize, XtRInt,
189     sizeof(int), offset(accumAlphaSize),
190     XtRImmediate, (XtPointer) 0
191   }, { // the attribute list
192     SoXtNattribList, SoXtCAttribList, XtRPointer,
193     sizeof(int *), offset(attribList),
194     XtRImmediate, (XtPointer) NULL
195   }, { // the visual info
196     SoXtNvisualInfo, SoXtCVisualInfo, SoXtRVisualInfo,
197     sizeof(XVisualInfo *), offset(visualInfo),
198     XtRImmediate, (XtPointer) NULL
199   },
200   // miscellaneous resources
201   {
202     SoXtNinstallColormap, SoXtCInstallColormap, XtRBoolean,
203     sizeof(Boolean), offset(installColormap),
204     XtRImmediate, (XtPointer) TRUE
205   }, {
206     SoXtNallocateBackground, SoXtCAllocateColors, XtRBoolean,
207     sizeof(Boolean), offset(allocateBackground),
208     XtRImmediate, (XtPointer) FALSE
209   }, {
210     SoXtNallocateOtherColors, SoXtCAllocateColors, XtRBoolean,
211     sizeof(Boolean), offset(allocateOtherColors),
212     XtRImmediate, (XtPointer) FALSE
213   }, {
214     SoXtNinstallBackground, SoXtCInstallBackground, XtRBoolean,
215     sizeof(Boolean), offset(installBackground),
216     XtRImmediate, (XtPointer) TRUE
217   }, {
218     SoXtNginitCallback, SoXtCCallback, XtRCallback,
219     sizeof(XtCallbackList), offset(ginitCallback),
220     XtRImmediate, (XtPointer) NULL
221   }, {
222     SoXtNinputCallback, SoXtCCallback, XtRCallback,
223     sizeof(XtCallbackList), offset(inputCallback),
224     XtRImmediate, (XtPointer) NULL
225   }, {
226     SoXtNresizeCallback, SoXtCCallback, XtRCallback,
227     sizeof(XtCallbackList), offset(resizeCallback),
228     XtRImmediate, (XtPointer) NULL
229   }, {
230     SoXtNexposeCallback, SoXtCCallback, XtRCallback,
231     sizeof(XtCallbackList), offset(exposeCallback),
232     XtRImmediate, (XtPointer) NULL
233   }, {
234     SoXtNrefresh, SoXtCRefresh, XtRBoolean,
235     sizeof(Boolean), offset(refresh),
236     XtRImmediate, (XtPointer) NULL
237   },
238 
239   // Changes to Motif primitive resources
240   {
241     XmNtraversalOn, XmCTraversalOn, XmRBoolean,
242     sizeof(Boolean), poffset(traversal_on),
243     XmRImmediate, (XtPointer) FALSE
244   },
245   // highlighting is normally disabled, as when Motif tries to disable
246   // highlighting, it tries to reset the color back to the parent's
247   // background (usually Motif blue).  Unfortunately, that is in a
248   // different colormap, and doesn't work too well.
249   {
250     XmNhighlightOnEnter, XmCHighlightOnEnter, XmRBoolean,
251     sizeof(Boolean), poffset(highlight_on_enter),
252     XmRImmediate, (XtPointer) FALSE
253   }, {
254     XmNhighlightThickness, XmCHighlightThickness, XmRHorizontalDimension,
255     sizeof(Dimension), poffset(highlight_thickness),
256     XmRImmediate, (XtPointer) 0
257   },
258 }; // resources
259 
260 /*
261 ** The following resources are reobtained using XtGetApplicationResources
262 ** in the initialize proc.
263 */
264 
265 // The colormap
266 static XtResource initializeResources[] =
267 {
268   // reobtain the colormap with the new visual
269   {
270     XtNcolormap, XtCColormap, XtRColormap,
271     sizeof(Colormap), coffset(colormap),
272     XtRCallProc,(XtPointer) createColormap
273   },
274 }; // initializeResources
275 
276 // reallocate any colors we need in the new colormap
277 // The background is obtained only if the allocateBackground resource is TRUE
278 
279 static XtResource backgroundResources[] =
280 {
281   {
282     XmNbackground, XmCBackground, XmRPixel,
283     sizeof(Pixel), coffset(background_pixel),
284     XmRString, (XtPointer) "lightgrey"
285   }, {
286     XmNbackgroundPixmap, XmCPixmap, XmRXmBackgroundPixmap,
287     sizeof(Pixmap), coffset(background_pixmap),
288     XmRImmediate, (XtPointer) XmUNSPECIFIED_PIXMAP
289   },
290 }; // backgroundResources
291 
292 // The other colors such as the foreground are allocated only if
293 // allocateOtherColors are set.  These resources only exist in Motif.
294 
295 static XtResource otherColorResources[] =
296 {
297   {
298     XmNforeground, XmCForeground, XmRPixel,
299     sizeof(Pixel), poffset(foreground),
300     XmRString, (XtPointer) "lighgrey"
301   }, {
302     XmNhighlightColor, XmCHighlightColor, XmRPixel,
303     sizeof(Pixel), poffset(highlight_color),
304     XmRString, (XtPointer) "lightgrey"
305   }, {
306     XmNhighlightPixmap, XmCHighlightPixmap, XmRPrimHighlightPixmap,
307     sizeof(Pixmap), poffset(highlight_pixmap),
308     XmRImmediate, (XtPointer) XmUNSPECIFIED_PIXMAP
309   },
310 }; // otherColorResources
311 
312 #undef coffset
313 #undef poffset
314 #undef offset
315 
316 SoXtGLAreaClassRec soxtGLAreaClassRec = {
317   { // core fields
318     (WidgetClass) &xmPrimitiveClassRec,    // superclass
319     "SoXtGLArea",                          // class_name
320     sizeof(SoXtGLAreaRec),                 // widget_size
321     NULL,                                  // class_initialize
322     NULL,                                  // class_part_initialize
323     FALSE,                                 // class_inited
324     (XtInitProc) Initialize,               // initialize
325     NULL,                                  // initialize_hook
326     Realize,                               // realize
327     SoXtGLArea_actions,                    // actions
328     XtNumber(SoXtGLArea_actions),          // num_actions
329     SoXtGLArea_resources,                  // resources
330     XtNumber(SoXtGLArea_resources),        // num_resources
331     NULLQUARK,                             // xrm_class
332     TRUE,                                  // compress_motion
333     TRUE,                                  // compress_exposure
334     TRUE,                                  // compress_enterleave
335     TRUE,                                  // visible_interest
336     (XtWidgetProc) Destroy,                // destroy
337     (XtWidgetProc) Resize,                 // resize
338     (XtExposeProc) Redraw,                 // expose
339     SoXtGLArea_set_values,                 // set_values
340     NULL,                                  // set_values_hook
341     XtInheritSetValuesAlmost,              // set_values_almost
342     NULL,                                  // get_values_hook
343     NULL,                                  // accept_focus
344     XtVersion,                             // version
345     NULL,                                  // callback_private
346     SoXtGLArea_defaultTranslations,        // tm_table
347     XtInheritQueryGeometry,                // query_geometry
348     XtInheritDisplayAccelerator,           // display_accelerator
349     NULL                                   // extension
350   }, {
351     XmInheritBorderHighlight,              // border_highlight
352     XmInheritBorderUnhighlight,            // border_unhighlight
353     XtInheritTranslations,                 // translations
354     NULL,                                  // arm_and_activate
355     NULL,                                  // get_resources
356     0,                                     // num get_resources
357     NULL                                   // extension
358   }, {
359     (XtPointer) NULL                       // extension
360   }
361 }; // soxtGLAreaClassRec
362 
363 WidgetClass soxtGLAreaWidgetClass = (WidgetClass) &soxtGLAreaClassRec;
364 
365 static void
error(Widget w,char * string)366 error(
367   Widget w,
368   char * string)
369 {
370   char buf[100];
371   sprintf(buf, "SoXtGLArea: %s\n", string);
372   XtAppError(XtWidgetToApplicationContext(w), buf);
373 } // error()
374 
375 static void
warning(Widget w,char * string)376 warning(
377   Widget w,
378   char * string)
379 {
380   char buf[100];
381   sprintf(buf, "SoXtGLArea: %s\n", string);
382   XtAppWarning(XtWidgetToApplicationContext(w), buf);
383 } // warning()
384 
385 // *************************************************************************
386 
387 // Initialize the attribList based on the attributes
388 
389 static void
createAttribList(SoXtGLAreaWidget widget)390 createAttribList(
391   SoXtGLAreaWidget widget)
392 {
393   int * ptr;
394   widget->soxtGLArea.attribList =
395     (int *) XtMalloc(ATTRIBLIST_SIZE * sizeof(int));
396   if (! widget->soxtGLArea.attribList)
397     error((Widget) widget, "Unable to allocate attribute list");
398   ptr = widget->soxtGLArea.attribList;
399   *ptr++ = GLX_BUFFER_SIZE;
400   *ptr++ = widget->soxtGLArea.bufferSize;
401   *ptr++ = GLX_LEVEL;
402   *ptr++ = widget->soxtGLArea.level;
403   if (widget->soxtGLArea.rgba) *ptr++ = GLX_RGBA;
404   if (widget->soxtGLArea.doublebuffer) *ptr++ = GLX_DOUBLEBUFFER;
405   if (widget->soxtGLArea.stereo) *ptr++ = GLX_STEREO;
406   *ptr++ = GLX_AUX_BUFFERS;
407   *ptr++ = widget->soxtGLArea.auxBuffers;
408   *ptr++ = GLX_RED_SIZE;
409   *ptr++ = widget->soxtGLArea.redSize;
410   *ptr++ = GLX_GREEN_SIZE;
411   *ptr++ = widget->soxtGLArea.greenSize;
412   *ptr++ = GLX_BLUE_SIZE;
413   *ptr++ = widget->soxtGLArea.blueSize;
414   *ptr++ = GLX_ALPHA_SIZE;
415   *ptr++ = widget->soxtGLArea.alphaSize;
416   *ptr++ = GLX_DEPTH_SIZE;
417   *ptr++ = widget->soxtGLArea.depthSize;
418   *ptr++ = GLX_STENCIL_SIZE;
419   *ptr++ = widget->soxtGLArea.stencilSize;
420   *ptr++ = GLX_ACCUM_RED_SIZE;
421   *ptr++ = widget->soxtGLArea.accumRedSize;
422   *ptr++ = GLX_ACCUM_GREEN_SIZE;
423   *ptr++ = widget->soxtGLArea.accumGreenSize;
424   *ptr++ = GLX_ACCUM_BLUE_SIZE;
425   *ptr++ = widget->soxtGLArea.accumBlueSize;
426   *ptr++ = GLX_ACCUM_ALPHA_SIZE;
427   *ptr++ = widget->soxtGLArea.accumAlphaSize;
428   *ptr++ = None;
429   assert((ptr - widget->soxtGLArea.attribList) < ATTRIBLIST_SIZE);
430 } // createAttribList()
431 
432 // *************************************************************************
433 // Initialize the visualInfo based on the attribute list
434 
435 static void
createVisualInfo(SoXtGLAreaWidget widget)436 createVisualInfo(
437   SoXtGLAreaWidget widget)
438 {
439   static XVisualInfo * visualInfo;
440   assert(widget->soxtGLArea.attribList);
441 
442   if (widget->soxtGLArea.visualInfo == NULL)
443     widget->soxtGLArea.visualInfo =
444       glXChooseVisual(XtDisplay(widget),
445                        XScreenNumberOfScreen(XtScreen(widget)),
446                        widget->soxtGLArea.attribList);
447   if (! widget->soxtGLArea.visualInfo)
448     error((Widget) widget, "requested visual not supported");
449 } // createVisualkInfo()
450 
451 // *************************************************************************
452 
453 /* Initialize the colormap based on the visual info.
454  * This routine maintains a cache of visual-infos to colormaps.  If two
455  * widgets share the same visual info, they share the same colormap.
456  * This function is called by the callProc of the colormap resource entry.
457  */
458 
459 static void
createColormap(SoXtGLAreaWidget widget,int offset,XrmValue * value)460 createColormap(
461   SoXtGLAreaWidget widget,
462   int offset,
463   XrmValue * value)
464 {
465   static struct cmapCache {
466     Visual * visual;
467     Colormap cmap;
468   } * cmapCache;
469   static int cacheEntries = 0;
470   static int cacheMalloced = 0;
471   register int i;
472 
473   assert(widget->soxtGLArea.visualInfo);
474 
475   // see if we can find it in the cache
476   for (i = 0; i < cacheEntries; i++) {
477     if (cmapCache[i].visual == widget->soxtGLArea.visualInfo->visual) {
478       value->addr = (char *) &cmapCache[i].cmap;
479       return;
480     }
481   }
482 
483   // not in the cache, create a new entry
484   if (cacheEntries >= cacheMalloced) {
485     // need to malloc a new one.  Since we are likely to have only a
486     // few colormaps, we allocate one the first time, and double
487     // each subsequent time.
488     if (cacheMalloced == 0) {
489       cacheMalloced = 1;
490       cmapCache = (struct cmapCache *) XtMalloc(sizeof(struct cmapCache));
491     } else {
492       cacheMalloced <<= 1;
493       cmapCache = (struct cmapCache *) XtRealloc((char *) cmapCache,
494                      sizeof(struct cmapCache) * cacheMalloced);
495     }
496   }
497 
498   cmapCache[cacheEntries].cmap =
499     XCreateColormap(XtDisplay(widget),
500                      RootWindow(XtDisplay(widget),
501                                 widget->soxtGLArea.visualInfo->screen),
502                      widget->soxtGLArea.visualInfo->visual,
503                      AllocNone);
504   cmapCache[cacheEntries].visual = widget->soxtGLArea.visualInfo->visual;
505   value->addr = (char *) &cmapCache[cacheEntries++].cmap;
506 } // createColormap()
507 
508 // *************************************************************************
509 
510 static void
Initialize(SoXtGLAreaWidget req,SoXtGLAreaWidget neww,ArgList args,Cardinal * num_args)511 Initialize(
512   SoXtGLAreaWidget req,
513   SoXtGLAreaWidget neww,
514   ArgList args,
515   Cardinal * num_args)
516 {
517   // fix size
518   if (req->core.width == 0) neww->core.width = 100;
519   if (req->core.height == 0) neww->core.width = 100;
520 
521   // create the attribute list if needed
522   neww->soxtGLArea.myList = FALSE;
523   if (neww->soxtGLArea.attribList == NULL) {
524     neww->soxtGLArea.myList = TRUE;
525     createAttribList(neww);
526   }
527 
528   // Gotta have it
529   assert(neww->soxtGLArea.attribList);
530 
531   // determine the visual info if needed
532   neww->soxtGLArea.myVisual = FALSE;
533   if (neww->soxtGLArea.visualInfo == NULL) {
534     neww->soxtGLArea.myVisual = TRUE;
535     createVisualInfo(neww);
536   }
537 
538   // Gotta have that too
539   assert(neww->soxtGLArea.visualInfo);
540 
541   neww->core.depth = neww->soxtGLArea.visualInfo->depth;
542 
543   // Reobtain the colormap and colors in it using XtGetApplicationResources
544   XtGetApplicationResources((Widget) neww, neww, initializeResources,
545     XtNumber(initializeResources), args, *num_args);
546 
547   // obtain the color resources if appropriate
548   if (req->soxtGLArea.allocateBackground) {
549     XtGetApplicationResources((Widget) neww, neww, backgroundResources,
550       XtNumber(backgroundResources), args, *num_args);
551   }
552 
553   if (req->soxtGLArea.allocateOtherColors) {
554     XtGetApplicationResources((Widget) neww, neww, otherColorResources,
555       XtNumber(otherColorResources), args, *num_args);
556   }
557 } // Initialize()
558 
559 // *************************************************************************
560 
561 static void
Realize(Widget widget,Mask * valueMask,XSetWindowAttributes * attributes)562 Realize(
563   Widget widget,
564   Mask * valueMask,
565   XSetWindowAttributes * attributes)
566 {
567   register SoXtGLAreaWidget glw = (SoXtGLAreaWidget) widget;
568   SoXtGLAreaCallbackStruct cb;
569   Widget parentShell;
570   Status status;
571   Window windows[2], * windowsReturn, * windowList;
572   int countReturn, i;
573 
574   // if we haven't requested that the background be both installed and
575   // allocated, don't install it.
576 
577   if (! (glw->soxtGLArea.installBackground &&
578           glw->soxtGLArea.allocateBackground))
579     *valueMask &= ~CWBackPixel;
580 
581   XtCreateWindow(widget, (unsigned int) InputOutput,
582     glw->soxtGLArea.visualInfo->visual, *valueMask, attributes);
583 
584   // if appropriate, call XSetWMColormapWindows to install the colormap
585   if (glw->soxtGLArea.installColormap) {
586 
587     // get parent shell
588     for (parentShell = XtParent(widget);
589           parentShell && ! XtIsShell(parentShell);
590           parentShell = XtParent(parentShell)) { }
591 
592     if (parentShell && XtWindow(parentShell)) {
593 
594       // check to see if there is already a property
595       status = XGetWMColormapWindows(XtDisplay(parentShell),
596                                       XtWindow(parentShell),
597                                       &windowsReturn, &countReturn);
598 
599       // if no property, just create one
600       if (! status) {
601         windows[0] = XtWindow(widget);
602         windows[1] = XtWindow(parentShell);
603         XSetWMColormapWindows(XtDisplay(parentShell), XtWindow(parentShell),
604                                windows, 2);
605       } else {
606         // there was a property, add myself to the beginning
607         windowList = (Window *) XtMalloc(sizeof(Window) * (countReturn+1));
608         windowList[0] = XtWindow(widget);
609         for (i = 0; i < countReturn; i++)
610           windowList[i+1] = windowsReturn[i];
611         XSetWMColormapWindows(XtDisplay(parentShell), XtWindow(parentShell),
612                                windowList, countReturn + 1);
613         XtFree((char *) windowList);
614         XtFree((char *) windowsReturn);
615       }
616     } else {
617       warning(widget, "Could not set colormap property on parent shell");
618     }
619   }
620   // Invoke init callbacks:
621   cb.reason = SoXtCR_GINIT;
622   cb.event = NULL;
623   cb.width = glw->core.width;
624   cb.height = glw->core.height;
625   XtCallCallbackList((Widget) glw, glw->soxtGLArea.ginitCallback, &cb);
626 } // Realize()
627 
628 // *************************************************************************
629 
630 static void
Redraw(SoXtGLAreaWidget widget,XEvent * event,Region region)631 Redraw(
632   SoXtGLAreaWidget widget,
633   XEvent * event,
634   Region region)
635 {
636   SoXtGLAreaCallbackStruct cb;
637   XtCallbackList cblist;
638   if (! XtIsRealized((Widget) widget))
639     return;
640   cb.reason = SoXtCR_EXPOSE;
641   cb.event = event;
642   cb.width = widget->core.width;
643   cb.height = widget->core.height;
644   XtCallCallbackList((Widget) widget, widget->soxtGLArea.exposeCallback, &cb);
645 } // Redraw()
646 
647 // *************************************************************************
648 
649 static void
Resize(SoXtGLAreaWidget glw)650 Resize(
651   SoXtGLAreaWidget glw)
652 {
653   SoXtGLAreaCallbackStruct cb;
654   if (! XtIsRealized((Widget) glw))
655     return;
656   cb.reason = SoXtCR_RESIZE;
657   cb.event = NULL;
658   cb.width = glw->core.width;
659   cb.height = glw->core.height;
660   XtCallCallbackList((Widget) glw, glw->soxtGLArea.resizeCallback, &cb);
661 } // Resize()
662 
663 // *************************************************************************
664 
665 static void
Destroy(SoXtGLAreaWidget glw)666 Destroy(
667   SoXtGLAreaWidget glw)
668 {
669   Window * windowsReturn;
670   Widget parentShell;
671   Status status;
672   int countReturn;
673   register int i;
674 
675   if (glw->soxtGLArea.myList && glw->soxtGLArea.attribList)
676     XtFree((char *) glw->soxtGLArea.attribList);
677 
678   if (glw->soxtGLArea.myVisual && glw->soxtGLArea.visualInfo)
679     XtFree((char *) glw->soxtGLArea.visualInfo);
680 
681   // if my colormap was installed, remove it
682   if (glw->soxtGLArea.installColormap) {
683     // Get parent shell
684     for (parentShell = XtParent(glw);
685           parentShell && ! XtIsShell(parentShell);
686           parentShell = XtParent(parentShell)) { }
687 
688     if (parentShell && XtWindow(parentShell)) {
689       // make sure there is a property
690       status = XGetWMColormapWindows(XtDisplay(parentShell),
691                                       XtWindow(parentShell),
692                                       &windowsReturn, &countReturn);
693 
694       // if no property, just return.  If there was a property, continue
695       if (status) {
696         // search for a match
697         for (i = 0; i < countReturn; i++) {
698           if (windowsReturn[i] == XtWindow(glw)) {
699             // we found a match, now copy the rest down
700             for (i++; i < countReturn; i++)
701               windowsReturn[i-1] = windowsReturn[i];
702 
703             XSetWMColormapWindows(XtDisplay(parentShell),
704               XtWindow(parentShell), windowsReturn, countReturn-1);
705             break;
706           }
707         }
708         XtFree((char *) windowsReturn);
709       }
710     }
711   }
712 } // Destroy()
713 
714 // *************************************************************************
715 
716 // Action routine for keyboard and mouse events
717 
718 static void
glwInput(SoXtGLAreaWidget glw,XEvent * event,String * params,Cardinal * numParams)719 glwInput(
720   SoXtGLAreaWidget glw,
721   XEvent * event,
722   String * params,
723   Cardinal * numParams)
724 {
725   SoXtGLAreaCallbackStruct cb;
726   cb.reason = SoXtCR_INPUT;
727   cb.event = event;
728   cb.width = glw->core.width;
729   cb.height = glw->core.height;
730   XtCallCallbackList((Widget) glw, glw->soxtGLArea.inputCallback, &cb);
731 } // glwInput()
732 
733 // *************************************************************************
734 
735 void
SoXtGLAreaMakeCurrent(Widget w,GLXContext ctx)736 SoXtGLAreaMakeCurrent(
737   Widget w,
738   GLXContext ctx)
739 {
740   glXMakeCurrent(XtDisplay(w), XtWindow(w), ctx);
741 } // SoXtGLAreaMakeCurrent()
742 
743 // *************************************************************************
744 
745 void
SoXtGLAreaSwapBuffers(Widget w)746 SoXtGLAreaSwapBuffers(
747   Widget w)
748 {
749   glXSwapBuffers(XtDisplay(w), XtWindow(w));
750 } // SoXtGLAreaSwapBuffers()
751 
752 // *************************************************************************
753 
754 Boolean
SoXtGLArea_set_values(Widget current,Widget request,Widget new_widget,ArgList args,Cardinal * num_args)755 SoXtGLArea_set_values(
756   Widget current,
757   Widget request,
758   Widget new_widget,
759   ArgList args,
760   Cardinal * num_args)
761 {
762   Boolean redisplay = False;
763   SoXtGLAreaWidget curcw = (SoXtGLAreaWidget) current;
764   SoXtGLAreaWidget reqcw = (SoXtGLAreaWidget) request;
765   SoXtGLAreaWidget newcw = (SoXtGLAreaWidget) new_widget;
766 
767   if (newcw->soxtGLArea.refresh != curcw->soxtGLArea.refresh) {
768     newcw->soxtGLArea.refresh = False;
769     redisplay = True;
770   }
771 
772   return redisplay;
773 } // SoXtGLArea_set_values()
774 
775 // *************************************************************************
776 
777